如何使用Python包装器提高Elasticsearch的准确性搜索结果?我的基本示例返回结果,但结果非常不准确。
我在Ubuntu 16上运行Elasticsearch 5.2,我首先创建索引并添加一些文档,如:
es = Elasticsearch()
# Document A
es.index(
index='my-test-index',
doc_type='text',
body=dict(
search_key='some specific keywords',
weight=1.0,
data='blah1',
),
)
# Document B
es.index(
index='my-test-index',
doc_type='text',
body=dict(
search_key='some other specific keywords',
weight=1.0,
data='blah2',
),
)
# Document C
es.index(
index='my-test-index',
doc_type='text',
body=dict(
search_key='some other very long text that is very different yet mentions the word specific and keywords',
weight=1.0,
data='blah3',
),
)
然后我用以下方式查询:
es = Elasticsearch()
es.indices.create(index='my-test-index', ignore=400)
query = 'some specific keywords'
results = es.search(
index='my-test-index',
body={
'query':{
"function_score": {
"query": {
"match": {
"search_key": query
}
},
"functions": [{
"script_score": {
"script": "doc['weight'].value"
}
}],
"score_mode": "multiply"
}
},
}
)
虽然它返回所有结果,但它按文档B,C,A的顺序返回它们,而我希望它们按顺序A,B,C,因为尽管所有文档都包含我的所有关键字,但只有第一个是完全匹配。我希望C是最后一个,因为即使它包含我的所有关键字,它也包含很多我没有明确搜索的漏洞。
当我索引更多条目时,此问题会更复杂。搜索会从我的查询中返回包含单个关键字的所有内容,并且看起来相同地对它们进行加权,导致搜索结果越小,我的索引越大,搜索结果就越准确。
这使得Elasticsearch几乎无用。无论如何我能解决它吗?我的search()
电话有问题吗?
答案 0 :(得分:2)
在您的查询中,您可以使用match_phrase
查询而不是match
查询,以便搜索字词的顺序和接近度进入混合状态。此外,您可以添加较小的slop
,以便使条款更加分开或以不同的顺序排列。但是,具有相同顺序和更近距离的条款的文档将比具有不按顺序和/或更远的条款的文档排名更高。试一试
"query": {
"match_phrase": {
"search_key": query,
"slop": 10
}
},
注意:slop
是一个数字,表示您需要执行多少"swaps"个搜索字词才能登陆文档中的术语配置。
答案 1 :(得分:0)
很抱歉没有仔细阅读您的问题以及下面加载的答案。我不想在泥泞中坚持下去,但我认为如果你更了解Elasticsearch本身是如何运作的话会更清楚。
由于您索引文档而未指定任何索引和mapping配置,因此Elasticsearch将使用它提供的几个默认设置。索引过程将首先使用standard tokenizer对文档中的字段值进行标记,然后使用the standard analyzer对其进行分析,然后将其存储在索引中。标准标记器和分析器都通过基于字边界分割字符串来工作。因此,在索引时间结束时,您在search_key
字段中的字词索引中的内容为["some", "specific", "keywords"]
,而不是"some specific keywords"
。
在搜索时间内,match
查询使用称为术语频率/反向文档频率或TF / IDF的相似性算法来控制relevance。这种算法在文本搜索中非常流行,并且有一个维基百科章节:https://en.wikipedia.org/wiki/Tf%E2%80%93idf。这里需要注意的重要一点是,您的术语出现在索引中的频率越高,相关性就越不重要。 some
,specific
和keywords
出现在索引中的所有3个文档中,因此就弹性搜索而言,它们对文档在搜索中的相关性贡献很小结果。由于A仅包含这些字词,因此在英文索引中只包含the
,an
,a
的文档。即使您专门搜索the
,an
,a
,它也不会显示为第一个结果。 B排名高于C,因为B较短,产生较高的标准值。该相关文档中解释了该范数值。这对我来说有点猜测,但如果您使用explain API解释查询,我认为它确实有效。
那么,回到你的需要,如何支持完全匹配而不是其他一切?当然,Val指出了match_phrase查询。另一种流行的方法(我个人更喜欢)是在定义映射时使用search_key.raw
选项在名为not_analyzed
的嵌套字段中索引原始值:https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping-intro.html#_index_2并简单地将其提升搜索时的原始值。