在索引文本时,我将每个单词的频率计数存储在数据库中。由于所有搜索都基于整个单词,并且所有可能的搜索都是已知的,因此这很好用。 但是现在我想添加前缀搜索(搜索词的一部分)的选项。我可以使用以下方法从带有Elasticsearch的前缀搜索中获得结果/匹配:
GET /my_index/address/_search
{
"query": {
"prefix": {
"main_text": "word_part"
}
}
}
请参阅:https://www.elastic.co/guide/en/elasticsearch/guide/current/prefix-query.html
这是我当前的映射:
{
"my-index":{
"mappings":{
"doc":{
"properties":{
"keycounter":{
"properties":{
"counter": {"type":"integer"},
"keyword":{"type":"keyword"}
}
},
"main_text":{
"type":"text",
"fielddata":true
},
"main_text_keycounter":{
"properties":{
"counter":{
"type":"long"
},
"keyword":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
}
}
},
"time_written":{
"type":"date"
},
"translated_text":{
"type":"text",
"fielddata":true
},
}
}
}
}
}
但是我不想为得到的每个结果计算频率,因为每个文本要花费O(N)。是否有一些使用Elasticsearch从这种类型的搜索中存储/获取频率计数的聪明方法?
答案 0 :(得分:2)
您可以使用elasticsearch的{{3}}功能来获取术语统计信息和术语计数。这样,您可以使用映射存储文档,并在查询时获取前缀术语的统计信息。当然,这种方法可以为您提供每个结果文档的字词统计信息,因此您必须将其汇总到所有结果中。
以下是映射,索引文档和doc-termvectors
查询的示例。您还可以使用doc-termvectors令牌生成器来获取前缀术语的统计信息。
映射:
PUT /my-index
{
"mappings": {
"doc": {
"properties": {
"main_text": {
"type": "text",
"fielddata": true,
"term_vector": "with_positions_offsets_payloads",
"store": true
}
}
}
}
}
索引文档:
POST /my-index/doc/1
{
"main_text": "foo bar foo"
}
获取术语向量:
POST /my-index/doc/1/_termvectors
结果:
...
"terms": {
...
"foo": {
"term_freq": 2,
"tokens": [
{
"position": 0,
"start_offset": 0,
"end_offset": 3
},
{
"position": 2,
"start_offset": 8,
"end_offset": 11
}
]
}
...
修改
如果要获取多份文档的termvectors
,可以使用edge-ngram端点。它将为您提供多个文档的统计信息。但是,据我所知,您要查询的内容不会计算所有文档的词频。作为解决方案,您可以将termvectors
的结果存储在弹性值(相同的索引或单独的索引)中,然后使用汇总来计算总的术语数。
POST /my-index/doc/_mtermvectors
{
"ids": [
"1",
"2"
],
"parameters": {
"fields": [
"main_text"
],
"term_statistics": true
}
}
修改
然后,我认为解决方案是为所有文档调用termvectors
并将结果(即所有术语和子术语的频率)存储在另一个索引中。通过基于搜索查询汇总结果,您将获得所需的结果。
答案 1 :(得分:0)
看看这个answer,建议使用有限状态转换器来加快completion suggester的前缀搜索。看起来很整洁,声称与Trie用法相当