【问题标题】:App engine - easy text search应用引擎 - 简单的文本搜索
【发布时间】:2010-10-11 16:48:02
【问题描述】:

我希望为 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"

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

【问题讨论】:

  • 发明自己的全文搜索真的比安装库更简单吗?还是使用 google.appengine.ext.db.searchablemodel?
  • 嗨尼克,什么是 google.appengine.ext.db.searchablemodel?我只能在网上找到短暂的参考。

标签: google-app-engine text-search


【解决方案1】:

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

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

来自the docs

db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop

这匹配每个 MyModel 实体 开始的字符串属性道具 与字符 abc。统一码 字符串 u"\ufffd" 表示 最大可能的 Unicode 字符。 属性值排序时 一个索引,属于这个的值 range 是所有开始的值 使用给定的前缀。

【讨论】:

  • 嘿,Drew,您关于这不能针对较大条目进行缩放的论点是合理的。但我很确定缩放并不像你计算的那么糟糕。比如5!是 5x4x3x2x1,但是当我完成它时,计算似乎实际上是 5+4+3+2+1(加法而不是乘法)。计算公式为 n*(n+1)/2。所以一个 500 个字符的字符串需要少于 125250 个索引......这仍然很多。
猜你喜欢
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多