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

时间:2015-11-30 11:47:05

标签: sorting search elasticsearch prefix

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

解释

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

测试我已经

数据

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"}
  

添加了映射以对原始值进行排序'测试

简单查询

查询

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. Kaley Bartoletti
  2. Kali Hahn
  3. Karolann Klein
  4. Berta Kassulke
  5. Sofia Mandez Kaloo

1 个答案:

答案 0 :(得分:1)

好问题。实现此目标的一种方法是edge ngram filterspan 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编写了以下查询。请注意,第一个end span query 参数为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"
            ]
         }
      ]

我希望这会有所帮助。