使用 Whoosh 生成搜索词建议?
Generating search term suggestions with Whoosh?
我在 Whoosh 索引中有一组文档,我想提供搜索词建议功能。因此,如果您键入 "pop",可能会出现一些建议:
- 爆米花
- 受欢迎
- 教皇
- 杨木片
- 流行文化
我已经得到了应该作为建议进入我的索引中的 NGRAMWORDS 字段的术语,但是当我对该字段进行查询时,我得到的是自动完成的结果而不是扩展的建议 - 所以我得到了文档用 "pop culture" 标记,但无法向用户显示该术语。
(为了比较,我会在 ElasticSearch 中使用该字段上的完成映射来执行此操作,然后使用 _suggest 端点来获取建议。)
我只能在文档或网络上的其他地方找到自动完成或拼写更正的示例。有什么方法可以使用 Whoosh 从我的索引中获取搜索词建议吗?
编辑:
expand_prefix
是朝着正确方向急需的指针。我最终为我的建议字段使用了 KEYWORD(commas=True, lowercase=True)
,并且像这样的代码以最常见的第一顺序获得建议(expand_prefix
和 iter_prefix
将按字母顺序产生它们) :
def get_suggestions(term):
with ix.reader() as r:
suggestions = [(s[0], s[1].doc_frequency()) for s in r.iter_prefix('suggest', term)]
return sorted(suggestions, key=itemgetter(1), reverse=True)
这不是您要查找的内容,但可能对您有所帮助:
reader = index.reader()
for x in r.expand_prefix('title', 'pop'):
print x
输出示例:
pop
popcorn
popular
更新
另一种解决方法是使用仅作为 TEXT 的关键字构建另一个索引。并使用搜索语言。我能达到的目标:
In [12]: list(ix.searcher().search(qp.parse('pop*')))
Out[12]:
[<Hit {'keywords': u'popcorn'}>,
<Hit {'keywords': u'popular'}>,
<Hit {'keywords': u'pope'}>,
<Hit {'keywords': u'Popular Film'}>,
<Hit {'keywords': u'pop culture'}>]
词频函数
我想补充一下这里的答案,whoosh 中实际上有一个内置函数 returns 按词频排列的前 'number' 个词。它位于 whoosh docs.
whoosh.reading.IndexReader.most_frequent_terms(fieldname, number=5, prefix='')
tf-idf 与频率
此外,在文档的同一页上,就在 whoosh docs is a function that returns the most distinctive terms rather than the most frequent. It uses the tf-idf 分数中前一个函数的正上方,它可以有效地消除常见但无关紧要的词,如 'the'。这可能或多或少有用,具体取决于您要查找的内容。它被恰当地命名为:
whoosh.reading.IndexReader.most_distinctive_terms(fieldname, number=5, prefix='')
其中每一个都将以这种方式使用:
with ix.reader() as r:
print r.most_frequent_terms('suggestions', number=5, prefix='pop')
print r.most_distinctive_terms('suggestions', number=5, prefix='pop')
多词建议
另外,我在使用多词建议时遇到了问题。我的解决方案是按以下方式创建模式:
fields.Schema(suggestions = fields.TEXT(),
suggestion_phrases = fields.KEYWORD(commas=True, lowercase=True)
在suggestion_phrases
字段中,commas=True
允许关键字以空格存储,因此有多个单词,lowercase=True
忽略大小写(如果需要可以去掉区分大写和非大写术语)。然后,为了同时获得单词和多词建议,您可以在两个字段上 运行 most_frequent_terms()
或 most_distinctive_terms()
。然后合并结果。
我在 Whoosh 索引中有一组文档,我想提供搜索词建议功能。因此,如果您键入 "pop",可能会出现一些建议:
- 爆米花
- 受欢迎
- 教皇
- 杨木片
- 流行文化
我已经得到了应该作为建议进入我的索引中的 NGRAMWORDS 字段的术语,但是当我对该字段进行查询时,我得到的是自动完成的结果而不是扩展的建议 - 所以我得到了文档用 "pop culture" 标记,但无法向用户显示该术语。 (为了比较,我会在 ElasticSearch 中使用该字段上的完成映射来执行此操作,然后使用 _suggest 端点来获取建议。)
我只能在文档或网络上的其他地方找到自动完成或拼写更正的示例。有什么方法可以使用 Whoosh 从我的索引中获取搜索词建议吗?
编辑:
expand_prefix
是朝着正确方向急需的指针。我最终为我的建议字段使用了 KEYWORD(commas=True, lowercase=True)
,并且像这样的代码以最常见的第一顺序获得建议(expand_prefix
和 iter_prefix
将按字母顺序产生它们) :
def get_suggestions(term):
with ix.reader() as r:
suggestions = [(s[0], s[1].doc_frequency()) for s in r.iter_prefix('suggest', term)]
return sorted(suggestions, key=itemgetter(1), reverse=True)
这不是您要查找的内容,但可能对您有所帮助:
reader = index.reader()
for x in r.expand_prefix('title', 'pop'):
print x
输出示例:
pop
popcorn
popular
更新
另一种解决方法是使用仅作为 TEXT 的关键字构建另一个索引。并使用搜索语言。我能达到的目标:
In [12]: list(ix.searcher().search(qp.parse('pop*')))
Out[12]:
[<Hit {'keywords': u'popcorn'}>,
<Hit {'keywords': u'popular'}>,
<Hit {'keywords': u'pope'}>,
<Hit {'keywords': u'Popular Film'}>,
<Hit {'keywords': u'pop culture'}>]
词频函数
我想补充一下这里的答案,whoosh 中实际上有一个内置函数 returns 按词频排列的前 'number' 个词。它位于 whoosh docs.
whoosh.reading.IndexReader.most_frequent_terms(fieldname, number=5, prefix='')
tf-idf 与频率
此外,在文档的同一页上,就在 whoosh docs is a function that returns the most distinctive terms rather than the most frequent. It uses the tf-idf 分数中前一个函数的正上方,它可以有效地消除常见但无关紧要的词,如 'the'。这可能或多或少有用,具体取决于您要查找的内容。它被恰当地命名为:
whoosh.reading.IndexReader.most_distinctive_terms(fieldname, number=5, prefix='')
其中每一个都将以这种方式使用:
with ix.reader() as r:
print r.most_frequent_terms('suggestions', number=5, prefix='pop')
print r.most_distinctive_terms('suggestions', number=5, prefix='pop')
多词建议
另外,我在使用多词建议时遇到了问题。我的解决方案是按以下方式创建模式:
fields.Schema(suggestions = fields.TEXT(),
suggestion_phrases = fields.KEYWORD(commas=True, lowercase=True)
在suggestion_phrases
字段中,commas=True
允许关键字以空格存储,因此有多个单词,lowercase=True
忽略大小写(如果需要可以去掉区分大写和非大写术语)。然后,为了同时获得单词和多词建议,您可以在两个字段上 运行 most_frequent_terms()
或 most_distinctive_terms()
。然后合并结果。