如何通过elasticsearch
中的以下参数查询和排序文本1 - 搜索查询在结果的第一部分中是准确的
2 - 搜索查询在结果的另一部分中是准确的
3 - 结果包含搜索查询的所有单词
例如:
我搜索时:i love dogs
结果必须分别为:
1- I love dogs
2 - i love dogs and birds
3 - birds good but i love dogs and horses
4 - Horses and i love dogs
5 - I love horses and dogs
6 - good dogs and i love horses
答案 0 :(得分:2)
可以实现所需的行为,但需要对映射和查询进行一些调整。
首先,这是映射:
PUT my_phrase_search
{
"mappings": {
"doc": {
"properties": {
"expected_position": {
"type": "long"
},
"my_phrase": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256,
"normalizer": "my_normalizer"
}
}
}
}
}
},
"settings": {
"index": {
"analysis": {
"normalizer": {
"my_normalizer": {
"filter": [
"lowercase"
],
"type": "custom"
}
}
}
}
}
}
注意:我添加了字段expected_position
,以便更轻松地评估结果。
现在,查询:
POST my_phrase_search/doc/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"should": [
{
"prefix": {
"my_phrase.keyword": "i love dogs"
}
}
],
"_name": "prefix",
"boost": 2
}
},
{
"bool": {
"should": [
{
"match": {
"my_phrase": "i love dogs"
}
}
],
"_name": "match"
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"my_phrase": "i love dogs"
}
}
],
"_name": "phrase",
"boost": 2
}
}
]
}
}
}
这给出了以下结果:
[
{
"_score": 4.015718,
"_source": {
"my_phrase": "I love dogs",
"expected_position": 1
},
"matched_queries": [
"match",
"phrase",
"prefix"
]
},
{
"_score": 3.233316,
"_source": {
"my_phrase": "i love dogs and birds",
"expected_position": 2
},
"matched_queries": [
"match",
"phrase",
"prefix"
]
},
{
"_score": 1.3836111,
"_source": {
"my_phrase": "birds good but i love dogs and horses ",
"expected_position": 3
},
"matched_queries": [
"match",
"phrase"
]
},
{
"_score": 1.2333161,
"_source": {
"my_phrase": "Horses and i love dogs",
"expected_position": 4
},
"matched_queries": [
"match",
"phrase"
]
},
{
"_score": 0.8630463,
"_source": {
"my_phrase": "I love horses and dogs",
"expected_position": 5
},
"matched_queries": [
"match"
]
},
{
"_score": 0.38110584,
"_source": {
"my_phrase": "good dogs and i love horses",
"expected_position": 6
},
"matched_queries": [
"match"
]
}
]
您可能想知道,它是如何运作的?这些变化都是必要的吗?让我们找出答案。
text
字段和match
查询? match
查询如下所示:
POST my_phrase/doc/_search
{
"query": {
"match": {
"my_phrase": "i love dogs"
}
}
}
这将为我们提供以下结果顺序:5 - 1 - 3 - 2 - 4 - 6
。
问题是,为什么查询"i love dogs"
没有返回完美匹配1- I love dogs
,作为第一个结果?为什么5 - I love horses and dogs
先出现?
在这种情况下,答案是avgFieldLength
,用于计算score,它是computed per shard,因此对于不同的文档可能略有不同。
很明显ES应该给我们从查询开始的结果。我们如何告诉ES更喜欢这些文件?
prefix
字段keyword
搜索
我们可以使用prefix
查询与match
查询联合bool
查询(在这种情况下可以大致解释为OR
),如下所示:
POST my_phrase/doc/_search
{
"query": {
"bool": {
"should": [
{
"prefix": {
"my_phrase.keyword": "i love dogs"
}
},
{
"match": {
"my_phrase": "i love dogs"
}
}
]
}
}
}
请注意,prefix
查询仅适用于keyword
类型,因为它需要将文档解释为一个大标记。
此查询为我们提供了以下结果顺序:2 - 5 - 1 - 3 - 4 - 6
。
以下是角色的情况:keyword
数据类型未经过分析,因此i
或I
会对此前缀搜索产生影响。
我们如何才能使keyword
不区分大小写?
keyword
案例内容这是通过在映射中定义normalizer来实现的:
PUT my_phrase2
{
"settings": {
"analysis": {
"normalizer": {
"my_normalizer": {
"type": "custom",
"char_filter": [],
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"doc": {
"properties": {
"my_phrase": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256,
"normalizer": "my_normalizer"
}
}
}
}
}
}
}
现在,相同的查询将为我们提供以下顺序:1 - 2 - 5 - 3 - 4 - 6
。
这已经相当不错了,但5 - I love horses and dogs
仍然过高 - 高于3 - birds good but i love dogs and horses
且匹配完全匹配。
match
查询不关心短语中单词的顺序。我们可以提升具有正确顺序的文档吗?
match_phrase
以提升词组匹配 match_phrase
查询确实支持原始订单中的令牌。让我们在查询中使用它:
POST my_phrase2/doc/_search
{
"query": {
"bool": {
"should": [
{
"prefix": {
"my_phrase.keyword": "i love dogs"
}
},
{
"match_phrase": {
"my_phrase": "i love dogs"
}
},
{
"match": {
"my_phrase": "i love dogs"
}
}
]
}
}
}
这为我们提供了以下顺序:1 - 2 - 3 - 5 - 4 - 6
。
5 - I love horses and dogs
仍然高于4 - Horses and i love dogs
。看起来短语匹配应该有利于4。
查询变得非常复杂,让我们找出文件实际匹配的部分。
可以为查询提供names,以便了解复杂问题的哪些部分实际生效:
POST my_phrase2/doc/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"should": [
{
"prefix": {
"my_phrase.keyword": "i love dogs"
}
}
],
"_name": "prefix"
}
},
...
感兴趣的文件的回复将给我们:
{
"_score": 0.8630463,
"_source": {
"my_phrase": "I love horses and dogs",
"expected_position": 5
},
"matched_queries": [
"match"
]
},
{
"_score": 0.82221067,
"_source": {
"my_phrase": "Horses and i love dogs",
"expected_position": 4
},
"matched_queries": [
"match",
"phrase"
]
},
Doc 5与phrase
部分不匹配。看起来得分波动再次打击了我们。
短语查询看起来更相关,有没有办法提升它?
有一种方法可以影响得分的计算,告诉ES查询的某些部分更重要,称为boost。以下是它的外观:
POST my_phrase2/doc/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"should": [
{
"prefix": {
"my_phrase.keyword": "i love dogs"
}
}
],
"_name": "prefix",
"boost": 2
}
},
{
"bool": {
"should": [
{
"match": {
"my_phrase": "i love dogs"
}
}
],
"_name": "match"
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"my_phrase": "i love dogs"
}
}
],
"_name": "phrase",
"boost": 2
}
}
]
}
}
}
这个为我们提供了所需的结果顺序:1 - 2 - 3 - 4 - 5 - 6
。
请注意,我们还提升了prefix
查询,因为我们希望降低match
的重要性。
尽管此查询完成了这项工作,但您可能希望执行大量的实际验证并进一步调整以确保足够的搜索结果。
完全符合这6个文档的查询可能不适合大型真实世界的集合,请将此答案作为优化的开始。
正如您所看到的,查询的所有部分都不是必需的:查询的名称可以很容易地省略,但在理解文档的匹配方式方面可以起到很好的帮助。
希望有所帮助!
答案 1 :(得分:0)
要获得所需的结果,您需要使用match_phrase_prefix
参数,例如max_expansions
示例,以便进一步阅读。
GET /_search
{
"query": {
"match_phrase_prefix" : {
"message" : "quick brown f"
}
}
}