我希望能够实现一个简单但有效的App Engine文本搜索,我可以使用它来发布app引擎的官方文本搜索功能。我看到那里有库,但安装新东西总是很麻烦。我想知道这是否是一个有效的策略:
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")
如果要查询多个属性,可以保存每个属性的索引。就我而言,我在小文本字段上使用它来实现一些自动建议功能,而不是在文档中实际搜索单词和短语匹配(您可以使用上面的博客文章实现)。事实证明这很简单,我真的不需要它的库。此外,我预计,如果有人在搜索“拉里”,他们将首先键入“La ...”,而不是从单词中间开始:“arry”。因此,如果属性是针对一个人的名字或类似的东西,索引只有从第一个字母开始的子串,所以“拉里”的索引只是{“l”,“la”,“lar”,“larr” “,”拉里“}
我为电话号码这样的数据做了一些不同的事情,你可能想要搜索从开头或中间数字开始的数据。在这种情况下,我只是存储了从长度为3的字符串开始的整个子串集,因此电话号码“123-456-7890”将是:{“123”,“234”,“345”,.... 。“123456789”,“234567890”,“1234567890”},总共(10 *((10 + 1)/ 2)) - (10 + 9)= 41个索引......其实我做的还多一点复杂,以便删除一些不太可能使用的子串,但你明白了。
然后你的查询将是: (Pseaudo代码) SELECT *来自Person WHERE firstNameSearchIndex ==“lar” phonenumberSearchIndex ==“1234”
app引擎的工作方式是,如果查询子字符串与属性中的任何子字符串匹配,则将其视为匹配。
答案 0 :(得分:2)
在实践中,这不会扩展。对于n个字符的字符串,您需要n个阶乘索引条目。 500字符的字符串需要1.2 * 10 ^ 1134索引来捕获所有可能的子字符串。在实体完成写入数据存储之前,您将死于老年。
search.SearchableModel等实现为每个单词创建一个索引条目,这更加真实。您无法搜索任意子字符串,但有一个技巧可以匹配前缀:
来自the docs:
db.GqlQuery(“SELECT * FROM MyModel 其中prop&gt; =:1 AND prop&lt; :2" , “abc”,你“abc”+ u“\ ufffd”)
这匹配每个MyModel实体 一个字符串属性prop开始 用字符abc。 unicode 字符串u“\ ufffd”代表 最大可能的Unicode字符。 当属性值排序时 一个索引,这个值就是这个 范围是所有开始的值 使用给定的前缀。