我们正在使用Elasticsearch从大量数据集中的大约十二个不同字段中返回不同的搜索字词建议。为实现这一目标,我们目前正在使用'terms'和'top_hits'聚合(术语聚合使用通配符)。我们还在自定义分析器上使用shingle_filter(min-size:2,max-size:3),因为该项目的要求之一是返回多字搜索术语的搜索建议。
我尝试过几种不同的方法,但都不是很有效。
我们想要返回建议的所有标准都放在_all字段中,该字段使用带有木瓦过滤器的自定义分析器:
'settings' : {
'analysis' : {
'analyzer' : {
'autocomplete_analyzer' : {
'type' : 'custom',
'tokenizer' : 'suggestion_tokenizer',
'filter' : [
'lowercase',
'shingle_filter'
]
},
},
'tokenizer' : {
'suggestion_tokenizer' : {
'type' : 'whitespace'
}
},
'filter' : {
'shingle_filter' : {
'type' : 'shingle',
'min_shingle_size' : 2,
'max_shingle_size' : 3
}
}
}
},
'mappings' : {
'core' : {
'_all' : {
'enabled' : 'yes',
'index' : 'analyzed',
'analyzer' : 'autocomplete_analyzer'
},
'properties' : {
'suggestion_criteria_1': {
'type' : 'multi_field',
'fields' : {
'analyzed' : {
'type' : 'string',
'index' : 'analyzed'
},
'suggestion_criteria_1': {
'type' : 'string',
'index' : 'not_analyzed',
'include_in_all' : 'yes'
}
}
},...
'filter_criteria_1': {
'type' : 'string',
'include_in_all' : 'no',
'index' : 'not_analyzed'
},...
}
}
}
聚合/查询utilzies过滤器和建议术语搜索数组,因为我们需要知道建议匹配来自哪个字段:
{
'from' : 0,
'size' : 0,
'query' : {
'filtered' : {
'filter' : {
'and' : [
{search filter array / optional}
]
}
}
},
'aggs' : {
'suggestions' : {
'terms' : {
'field' : '_all',
'include' : '.*{search_term}.*'
},
'aggs' : {
'field_matches' : {
'top_hits' : {
'_source' : {
'include' : {criteria_array}
},
'size' : 1
}
}
}
}
}
};
在应用过滤器之后,我们正在处理一组大约10万个文档,结果会在500毫秒内返回,这比理想的搜索建议要长得多。
为简洁起见,我将仅描述上面的索引结构和查询/聚合的更改。
我禁用了_all字段,而是将“autocomplete_analyzer”(包括shingle_filter)应用于映射中的每个建议标准本身(其中大约有十几个)。
然后将所有建议条款添加到查询/聚合...
'aggs' : {
'suggestion_term_1' : {
'terms' : {
'field' : 'suggestion_term_1',
'include' : '.*{search_term}.*'
},
'aggs' : {
'field_matches' : {
'top_hits' : {
'_source' : {
'include' : 'suggestion_term_1'
},
'size' : 1
}
}
}
},
'suggestion_term_2' : {
'terms' : {
'field' : 'suggestion_term_2',
'include' : '.*{search_term}.*'
},
'aggs' : {
'field_matches' : {
'top_hits' : {
'_source' : {
'include' : 'suggestion_term_2'
},
'size' : 1
}
}
}
},
etc...
}
};
一旦应用过滤器,这也会超过500毫秒。仍然不理想。
这类似于方法2,但是不是在聚合中包括所有建议条款,而是在每个请求中仅包括一个术语。然后,我迭代建议条款,并为十几个标准中的每一个执行多个弹性搜索聚合请求。
大多数结果在20-30ms左右回来,但是当在整个迭代中求和时,我们在总请求时间内仍然在300-400ms之内。
我应该注意,作为使用通配符搜索词的替代方法,我也尝试将Edge nGram过滤器应用于分析器。然而,这通常会使总响应时间增加50-70%并使指数大小膨胀,从而没有明显的性能优势,因此我选择坚持使用通配符方法。
我还应该注意到,当我删除木瓦过滤器时,我看到了显着的性能改进,但不幸的是,多字查询是项目的必要条件。
我怀疑可能有一两种方法我还没有尝试过,这会让我们显着提高性能时间,但在这一点上我基本上都在抓稻草。任何建议都将不胜感激。