如何按匹配排序,优先匹配最左边的单词

How to sort by match prioritising the most left words matched

如何按匹配项排序,优先匹配最左边的单词

说明

按匹配的单词对前缀查询进行排序,但优先匹配左侧更多的单词。

我做过的测试

数据

DELETE /test
PUT /test

PUT /test/person/_mapping
{
  "properties": {
    "name": {
      "type": "multi_field",
      "fields": {
        "name": {"type": "string"},
        "original": {
          "type": "string", 
          "index": "not_analyzed"
        }
      }
    }
  }
}

PUT /test/person/1
{"name": "Berta Kassulke"}

PUT /test/person/2
{"name": "Kaley Bartoletti"}

PUT /test/person/3
{"name": "Kali Hahn"}

PUT /test/person/4
{"name": "Karolann Klein"}

PUT /test/person/5
{"name": "Sofia Mandez Kaloo"}

The mapping was added for the 'sort on original value' test.

简单查询

查询

POST /test/person/_search
{
  "query": {
    "prefix": {"name": {"value": "ka"}}
  }
}

结果

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 1,
    "hits": [
      {
        "_index": "test",
        "_type": "person",
        "_id": "4",
        "_score": 1,
        "_source": {
          "name": "Karolann Klein"
        }
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "5",
        "_score": 1,
        "_source": {
          "name": "Sofia Mandez Kaloo"
        }
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "Berta Kassulke"
        }
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "Kaley Bartoletti"
        }
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "Kali Hahn"
        }
      }
    ]
  }
}

带排序

请求

POST /test/person/_search
{
  "query": {
    "prefix": {"name": {"value": "ka"}}
  },
  "sort": {"name": {"order": "asc"}}
}

结果

{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": null,
    "hits": [
      {
        "_index": "test",
        "_type": "person",
        "_id": "2",
        "_score": null,
        "_source": {
          "name": "Kaley Bartoletti"
        },
        "sort": [
          "bartoletti"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "1",
        "_score": null,
        "_source": {
          "name": "Berta Kassulke"
        },
        "sort": [
          "berta"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "3",
        "_score": null,
        "_source": {
          "name": "Kali Hahn"
        },
        "sort": [
          "hahn"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "5",
        "_score": null,
        "_source": {
           "name": "Sofia Mandez Kaloo"
        },
        "sort": [
          "kaloo"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "4",
        "_score": null,
        "_source": {
          "name": "Karolann Klein"
        },
        "sort": [
          "karolann"
        ]
      }
    ]
  }
}

按原始值排序

查询

POST /test/person/_search
{
  "query": {
    "prefix": {"name": {"value": "ka"}}
  },
  "sort": {"name.original": {"order": "asc"}}
}

结果

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": null,
    "hits": [
      {
        "_index": "test",
        "_type": "person",
        "_id": "1",
        "_score": null,
        "_source": {
          "name": "Berta Kassulke"
        },
        "sort": [
          "Berta Kassulke"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "2",
        "_score": null,
        "_source": {
          "name": "Kaley Bartoletti"
        },
        "sort": [
          "Kaley Bartoletti"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "3",
        "_score": null,
        "_source": {
          "name": "Kali Hahn"
        },
        "sort": [
          "Kali Hahn"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "4",
        "_score": null,
        "_source": {
          "name": "Karolann Klein"
        },
        "sort": [
          "Karolann Klein"
        ]
      },
      {
        "_index": "test",
        "_type": "person",
        "_id": "5",
        "_score": null,
        "_source": {
           "name": "Sofia Mandez Kaloo"
        },
        "sort": [
          "Sofia Mandez Kaloo"
        ]
      }
    ]
  }
}

预期结果

按名称 ASC 排序,但优先匹配最左边的词

  1. 凯莉·巴托莱蒂
  2. 卡莉·哈恩
  3. 卡罗兰·克莱恩
  4. 贝尔塔·卡苏克
  5. 索菲亚·曼德斯·卡鲁

好问题。实现这一目标的一种方法是结合 edge ngram filter and span first query

这是我的设置

{
    "settings": {
        "analysis": {
            "analyzer": {
                "my_custom_analyzer": {
                    "tokenizer": "standard",
                    "filter": ["lowercase",
                        "edge_filter",
                        "asciifolding"
                    ]
                }
            },
            "filter": {
                "edge_filter": {
                    "type": "edgeNGram",
                    "min_gram": 2,
                    "max_gram": 8
                }

            }

        }
    },
    "mappings": {
        "person": {
            "properties": {
                "name": {
                    "type": "string",
                    "analyzer": "my_custom_analyzer",
                    "search_analyzer": "standard",
                    "fields": {
                        "standard": {
                            "type": "string"
                        }
                    }
                }
            }
        }

    }
}

之后我插入了您的示例文档。然后我用 dis_max 写了下面的查询。请注意,第一个 span queryend 参数为 1,因此这将 优先(更高的分数) 最左边的匹配。我先按 score 排序,然后按 name.

排序
{
  "query": {
    "dis_max": {
      "tie_breaker": 0.7,
      "boost": 1.2,
      "queries": [
        {
          "match": {
            "name": "ka"
          }
        },
        {
          "span_first": {
            "match": {
              "span_term": {
                "name": "ka"
              }
            },
            "end": 1
          }
        },
        {
          "span_first": {
            "match": {
              "span_term": {
                "name": "ka"
              }
            },
            "end": 2
          }
        }
      ]
    }
  },
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "name.standard": {
        "order": "asc"
      }
    }
  ]
}

我得到的结果

"hits": [
         {
            "_index": "esedge",
            "_type": "policy_data",
            "_id": "2",
            "_score": 0.72272325,
            "_source": {
               "name": "Kaley Bartoletti"
            },
            "sort": [
               0.72272325,
               "bartoletti"
            ]
         },
         {
            "_index": "esedge",
            "_type": "policy_data",
            "_id": "3",
            "_score": 0.72272325,
            "_source": {
               "name": "Kali Hahn"
            },
            "sort": [
               0.72272325,
               "hahn"
            ]
         },
         {
            "_index": "esedge",
            "_type": "policy_data",
            "_id": "4",
            "_score": 0.72272325,
            "_source": {
               "name": "Karolann Klein"
            },
            "sort": [
               0.72272325,
               "karolann"
            ]
         },
         {
            "_index": "esedge",
            "_type": "policy_data",
            "_id": "1",
            "_score": 0.54295504,
            "_source": {
               "name": "Berta Kassulke"
            },
            "sort": [
               0.54295504,
               "berta"
            ]
         },
         {
            "_index": "esedge",
            "_type": "policy_data",
            "_id": "5",
            "_score": 0.2905494,
            "_source": {
               "name": "Sofia Mandez Kaloo"
            },
            "sort": [
               0.2905494,
               "kaloo"
            ]
         }
      ]

希望对您有所帮助。