我需要使用 Elasticsearch 改进搜索结果列表。
假设我们有 3 个具有单个字段和内容的文档,如下所示:
如果我搜索“apple”,它可能会发生,我得到的结果是这样排序的:
但我想要的是具有最高分的精确匹配,这里是带有“apple”的文档。
下一个最高分应该是以搜索词开头的条目,这里是“苹果树”,其余排序默认方式。
所以我想拥有它:
我试图通过使用 rescore 来实现它:
curl -X GET "http://localhost:9200/my_index_name/_search?size=10&pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"query_string": {
"query": "apple"
}
},
"rescore": {
"window_size": 500,
"query": {
"score_mode": "multiply",
"rescore_query": {
"bool": {
"should": [
{
"match": {
"my_field1": {
"query": "apple",
"boost": 4
}
}
},
{
"match": {
"my_field1": {
"query": "apple*",
"boost": 2
}
}
}
]
}
},
"query_weight": 0.7,
"rescore_query_weight": 1.2
}
}
}'
Run Code Online (Sandbox Code Playgroud)
但这并不是真的有效,因为 Elasticsearch 似乎用空格分隔所有单词。例如,搜索“apple*”也会提供“green apple”。这似乎是 rescore 对我不起作用的原因。
可能还有其他字符,如点“.”、“-”、“;” Elasticsearch 用于拆分和弄乱我的排序等。
我还在“rescore_query”而不是“bool”中使用了“match_phrase”,但没有成功。
我也尝试过只有一场比赛:
curl -X GET "http://localhost:9200/my_index_name/_search?size=10&pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"query_string": {
"query": "apple"
}
},
"rescore": {
"window_size": 500,
"query": {
"score_mode": "multiply",
"rescore_query": {
"bool": {
"should": [
{
"match": {
"my_field1": {
"query": "apple*",
"boost": 2
}
}
}
]
}
},
"query_weight": 0.7,
"rescore_query_weight": 1.2
}
}
}'
Run Code Online (Sandbox Code Playgroud)
它似乎有效,但我仍然不确定。这是正确的方法吗?
EDIT1:对于其他查询,一个匹配重新评分无法正常工作。
您需要对分数进行操作的唯一地方是完全匹配,否则按术语位置的顺序会给您正确的顺序。让我们通过以下方式理解这一点:
让我们首先创建一个映射如下:
PUT test
{
"mappings": {
"_doc": {
"properties": {
"my_field1": {
"type": "text",
"analyzer": "whitespace",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经my_field1用whitespace分析器创建了字段,以确保通过使用空格作为唯一的分隔符来创建令牌。其次,我创建了一个名为 askeyword类型的子字段keyword。keyword将保存输入字符串的未分析值,我们将使用它进行精确匹配。
让我们向索引添加一些文档:
PUT test/_doc/1
{
"my_field1": "apple"
}
PUT test/_doc/2
{
"my_field1": "apple tree"
}
PUT test/_doc/3
{
"my_field1": "green apple"
}
Run Code Online (Sandbox Code Playgroud)
如果使用以下查询来搜索术语apple,则文档的顺序将为 2,1,3。
POST test/_doc/_search
{
"explain": true,
"query": {
"query_string": {
"query": "apple",
"fields": [
"my_field1"
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
"explain": true在上面的查询中给出输出中的分数计算步骤。阅读本文将使您深入了解文档是如何评分的。
我们需要做的就是提高精确匹配的分数。我们将对 field 进行精确匹配my_field1.keyword。您可能有一个问题,为什么不呢my_field1。这样做的原因是因为my_field1经过分析,当为 3 个文档的输入字符串生成令牌时,所有这些都将针对此字段存储一个令牌(术语)apple(以及其他术语,如果存在,例如treedoc 2 和greendoc 3) . 当我们在这个字段上为术语运行完全匹配时,apple所有文档都将匹配并对每个文档的分数产生类似的影响,因此分数没有变化。由于只有一个文档具有apple针对my_field1.keyword该文档(文档 1)的精确值,因此将与精确查询匹配,因此我们将提升这一点。所以查询将是:
{
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "apple",
"fields": [
"my_field1"
]
}
},
{
"query_string": {
"query": "\"apple\"",
"fields": [
"my_field1.keyword^2"
]
}
}
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
上述查询的输出:
{
"took": 9,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1.7260925,
"hits": [
{
"_index": "test3",
"_type": "_doc",
"_id": "1",
"_score": 1.7260925,
"_source": {
"my_field1": "apple"
}
},
{
"_index": "test3",
"_type": "_doc",
"_id": "2",
"_score": 0.6931472,
"_source": {
"my_field1": "apple tree"
}
},
{
"_index": "test3",
"_type": "_doc",
"_id": "3",
"_score": 0.2876821,
"_source": {
"my_field1": "green apple"
}
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1889 次 |
| 最近记录: |