0

我希望为 App Engine 实现一个简单但有效的文本搜索,直到应用引擎的官方文本搜索功能发布之前我都可以使用它。我看到那里有图书馆,但安装新东西总是很麻烦。我想知道这是否是一个有效的策略:

1) 将需要文本搜索的每个属性分解为一组文本片段 (列表) 2) 添加这些列表保存记录 3) 搜索时,只需在列表属性上使用相等过滤器

例如,如果我有记录:

{
  firstName="Jon";
  lastName="Doe";
}

我可以保存这样的属性:

{
  firstName="Jon";
  lastName="Doe";

  // not case sensative:
  firstNameSearchable=["j","o", "n","jo","on","jon"];   
  lastNameSerachable=["D","o","e","do","oe","doe"];
}

然后进行搜索,我可以这样做并期望它返回上述记录:

//pseudo-code:
SELECT person 
WHERE firstNameSearchable=="jo" AND
      lastNameSearchable=="oe"

这是文本搜索的实现方式吗?你如何防止索引失控,特别是如果你有一个段落或什么的?是否有其他一些通常使用的压缩策略?我想如果我只是想要一些简单的东西,这可能会奏效,但很高兴知道我可能遇到的问题。

更新:::

好的,所以事实证明这个概念可能是合法的。这篇博文也引用了它:http: //googleappengine.blogspot.com/2010/04/making-your-app-searchable-using-self.html

注意:上面博文中的源代码不适用于当前版本的 Lucene。我安装了旧版本(2.9.3)作为快速修复,因为谷歌应该很快就会推出他们自己的应用引擎文本搜索。

下面的响应中建议的解决方案是一个很好的快速修复,但由于大表的限制,仅当您查询一个字段时才有效,因为您只能在查询中的一个属性上使用不等式运算符:

db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2", "abc", u"abc" + u"\ufffd")

如果要查询多个属性,可以为每个属性保存索引。就我而言,我将它用于小文本字段的一些自动建议功能,而不是实际搜索文档中的单词和短语匹配(您可以使用上面的博客文章实现)。事实证明这很简单,我真的不需要图书馆。另外,我预计如果有人在搜索“Larry”,他们会从输入“La...”开始,而不是从单词中间开始:“arry”。所以如果属性是一个人的名字或类似的东西,索引只有以第一个字母开头的子字符串,所以“Larry”的索引只是{“l”,“la”,“lar”,“larr ", "拉里"}

我对电话号码等数据做了一些不同的事情,您可能希望从开头或中间数字开始搜索一个。在这种情况下,我只是存储了以长度为 3 的字符串开头的整个子字符串集,因此电话号码“123-456-7890”将是:{“123”、“234”、“345”、...。 . "123456789", "234567890", "1234567890"}, 一共 (10*((10+1)/2))-(10+9) = 41 个索引...其实我做的多一点复杂的,以便删除一些不太可能使用的子字符串,但你明白了。

那么您的查询将是:(伪代码)SELECT * from Person WHERE firstNameSearchIndex == "lar" phonenumberSearchIndex == "1234"

应用引擎的工作方式是,如果查询子字符串与属性中的任何子字符串匹配,则将其计为匹配。

4

1 回答 1

2

在实践中,这不会扩展。对于 n 个字符的字符串,您需要 n 个阶乘索引条目。一个 500 个字符的字符串需要 1.2 * 10^1134 个索引来捕获所有可能的子字符串。在您的实体完成写入数据存储之前,您将死于老年。

像 search.SearchableModel 这样的实现为每个单词创建一个索引条目,这更现实一些。您不能搜索任意子字符串,但有一个技巧可以让您匹配前缀:

文档

db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2", "abc", u"abc" + u"\ufffd")

这将每个 MyModel 实体与以字符 abc 开头的字符串属性 prop 匹配。unicode 字符串 u"\ufffd" 表示最大可能的 Unicode 字符。当属性值在索引中排序时,落在此范围内的值是所有以给定前缀开头的值。

于 2010-10-11T17:32:23.817 回答