问题 在elasticsearch中搜索带空格的名称(文本)


搜索包含空格的名称(文本),给我带来问题, 我有类似的映射

"{"user":{"properties":{"name":{"type":"string"}}}}"

理想情况下它应返回并按如下方式对结果进行排名

1) Bring on top names that exact match the search term (highest score)
2) Names that starts with the search term (high score)
3) Names that contains the exact search term as substring (medium score)
4) Names that contains any of the search term token  (lowest score)

例 对于elasticsearch中的以下名称

Maaz Tariq
Ahmed Maaz Tariq
Maaz Sheeba
Maaz Bin Tariq
Sana Tariq
Maaz Tariq Ahmed

搜索“Maaz Tariq”,结果应按以下顺序排列

Maaz Tariq (highest score)
Maaz Tariq Ahmed (high score)
Ahmed Maaz Tariq (medium score)
Maaz Bin Tariq  (lowest score)
Maaz Sheeba (lowest score)
Sana Tariq (lowest score)

任何人都可以指出我如何使用和使用哪种分析仪?以及如何对名称的搜索结果进行排名?


11560
2018-05-23 08:17


起源



答案:


你可以使用 多字段类型, 一个 布尔查询 和 自定义提升因子查询 解决这个问题。

制图:

{
    "mappings" : {
        "user" : {        
            "properties" : {
                "name": {
                    "type": "multi_field",
                    "fields": {
                        "name": { "type" : "string", "index": "analyzed" },
                        "exact": { "type" : "string", "index": "not_analyzed" }
                    }
                }
            }
        }
    }
}

查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Maaz Tariq"
                    }
                }
            ],
            "should": [
                {
                    "custom_boost_factor": {
                        "query": {
                            "term": {
                                "name.exact": "Maaz Tariq"
                            }
                        },
                        "boost_factor": 15
                    }
                },
                {
                    "custom_boost_factor": {
                        "query": {
                            "prefix": {
                                "name.exact": "Maaz Tariq"
                            }
                        },
                        "boost_factor": 10
                    }
                },
                {
                    "custom_boost_factor": {
                        "query": {
                            "match_phrase": {
                                "name": {
                                    "query": "Maaz Tariq",
                                    "slop": 0
                                }
                            }
                        },
                        "boost_factor": 5
                    }
                }
            ]
        }
    }
}

编辑:

正如javanna指出的那样 custom_boost_factor 不需要。

查询没有 custom_boost_factor

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Maaz Tariq"
                    }
                }
            ],
            "should": [
                {
                    "term": {
                        "name.exact": {
                            "value": "Maaz Tariq",
                            "boost": 15
                        }
                    }
                },
                {
                    "prefix": {
                        "name.exact": {
                            "value": "Maaz Tariq",
                            "boost": 10
                        }
                    }
                },
                {
                    "match_phrase": {
                        "name": {
                            "query": "Maaz Tariq",
                            "slop": 0,
                            "boost": 5
                        }
                    }
                }
            ]
        }
    }
}

9
2018-05-23 17:15



我更喜欢基于过滤器的解决方案,但我无法为3.要求找到合适的过滤器。 - Ivaldi
你可以为它做一个短语查询。另外,我不明白为什么你需要custom_boost_factor查询。你能不能用你的不同查询给出不同的权重 boost 选项? - javanna
Boost 是不允许的 should 子查询!? (至少我不知道这个的语法。)如果一个短语查询过滤器如何工作没有 span_near 查询,没有 match_phrase 查询? - Ivaldi
据我所知,每个查询都支持boost。实际上,短语查询是你用match_phrase做的,没有意识到! - javanna
我尝试过这个。如果我添加一个 boost 到子查询它变得无效。 - Ivaldi


答案:


你可以使用 多字段类型, 一个 布尔查询 和 自定义提升因子查询 解决这个问题。

制图:

{
    "mappings" : {
        "user" : {        
            "properties" : {
                "name": {
                    "type": "multi_field",
                    "fields": {
                        "name": { "type" : "string", "index": "analyzed" },
                        "exact": { "type" : "string", "index": "not_analyzed" }
                    }
                }
            }
        }
    }
}

查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Maaz Tariq"
                    }
                }
            ],
            "should": [
                {
                    "custom_boost_factor": {
                        "query": {
                            "term": {
                                "name.exact": "Maaz Tariq"
                            }
                        },
                        "boost_factor": 15
                    }
                },
                {
                    "custom_boost_factor": {
                        "query": {
                            "prefix": {
                                "name.exact": "Maaz Tariq"
                            }
                        },
                        "boost_factor": 10
                    }
                },
                {
                    "custom_boost_factor": {
                        "query": {
                            "match_phrase": {
                                "name": {
                                    "query": "Maaz Tariq",
                                    "slop": 0
                                }
                            }
                        },
                        "boost_factor": 5
                    }
                }
            ]
        }
    }
}

编辑:

正如javanna指出的那样 custom_boost_factor 不需要。

查询没有 custom_boost_factor

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Maaz Tariq"
                    }
                }
            ],
            "should": [
                {
                    "term": {
                        "name.exact": {
                            "value": "Maaz Tariq",
                            "boost": 15
                        }
                    }
                },
                {
                    "prefix": {
                        "name.exact": {
                            "value": "Maaz Tariq",
                            "boost": 10
                        }
                    }
                },
                {
                    "match_phrase": {
                        "name": {
                            "query": "Maaz Tariq",
                            "slop": 0,
                            "boost": 5
                        }
                    }
                }
            ]
        }
    }
}

9
2018-05-23 17:15



我更喜欢基于过滤器的解决方案,但我无法为3.要求找到合适的过滤器。 - Ivaldi
你可以为它做一个短语查询。另外,我不明白为什么你需要custom_boost_factor查询。你能不能用你的不同查询给出不同的权重 boost 选项? - javanna
Boost 是不允许的 should 子查询!? (至少我不知道这个的语法。)如果一个短语查询过滤器如何工作没有 span_near 查询,没有 match_phrase 查询? - Ivaldi
据我所知,每个查询都支持boost。实际上,短语查询是你用match_phrase做的,没有意识到! - javanna
我尝试过这个。如果我添加一个 boost 到子查询它变得无效。 - Ivaldi


在Java Api的情况下,当使用空格查询确切的字符串时;

CLIENT.prepareSearch(index)
    .setQuery(QueryBuilders.queryStringQuery(wordString)
    .field(fieldName));

在许多其他查询中,您得不到任何结果


0
2017-07-29 17:59





从Elasticsearch 1.0:

"title": {
    "type": "multi_field",
    "fields": {
        "title": { "type": "string" },
        "raw":   { "type": "string", "index": "not_analyzed" }
    }
}

成为:

"title": {
    "type": "string",
    "fields": {
        "raw":   { "type": "string", "index": "not_analyzed" }
    }
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html


0
2018-05-27 11:32