【问题标题】:How to write an elastic search query that matches and then filters the records?如何编写匹配然后过滤记录的弹性搜索查询?
【发布时间】:2020-01-08 13:08:15
【问题描述】:

在 Elastic Search 中,我编写了一个匹配搜索词并获取结果的查询。 这是我使用的查询。

  {
    "size": 40,
    "query": {
      "bool": {
        "must": [
          {
            "match": {
              "name": {
                "query": "Salem Chennai",
                "fuzziness": 1,
                "prefix_length": 2,
                "operator": "or"
              }
            }
          }
        ]
      }
    }
  }

这是我得到的回复:

    "timed_out": false,
    "_shards": {
      "total": 5,
      "successful": 5,
      "skipped": 0,
      "failed": 0
    },
    "hits": {
      "total": 2,
      "max_score": 11.182817,
      "hits": [
        {
          "_index": "locations",
          "_type": "city",
          "_id": "1610",
          "_score": 11.182817,
          "_source": {
            "name": "Chennai",
            "code": "IN-TN-CENAI",
            "province_name": "Tamil Nadu",
            "province_code": "IN-TN",
            "country_name": "India",
            "country_code": "IN"
          }
        },
        {
          "_index": "locations",
          "_type": "city",
          "_id": "24216",
          "_score": 9.688159,
          "_source": {
            "name": "Salem",
            "code": "US-IN-SALEM",
            "province_name": "Indiana",
            "province_code": "US-IN",
            "country_name": "United States",
            "country_code": "US"
          }
        }
    ]
  }

现在我想过滤在 country_code 上传递的响应。

所以我尝试了这个查询

{
    "size": 40,
    "query": {
      "bool": {
        "must": [
          {
            "match": {
              "name": {
                "query": "Salem Chennai",
                "fuzziness": 1,
                "prefix_length": 2,
                "operator": "or"
              }
            }
          }
        ],
        "filter": [
          {
            "term": {
              "country_name": "India"
            }
          }
        ]
      }
    }
  }

这是索引映射:

{
  "locations" : {
    "mappings" : {
      "city" : {
        "properties" : {
          "code" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "country_code" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "country_id" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "country_name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "id" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "province_code" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "province_country_code" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "province_country_id" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "province_country_name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "province_id" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "province_name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}

我应该得到一个结果,但是,这个查询没有给我任何结果。 有人可以帮我写一个可以匹配然后从弹性搜索中过滤记录的正确查询吗?

我以此为参考: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html#query-filter-context-ex

【问题讨论】:

  • 嗨,Surya,你能分享你的地图吗?
  • 如果你不关心分数(我认为是这种情况),你不应该使用过滤器,而是添加另一个必须布尔查询。 +1 关于我们需要的映射,country_name 需要映射为关键字。
  • @baitmbarek 已更新问题本身的映射,请检查

标签: elasticsearch search lucene


【解决方案1】:

您应该使用您的关键字进行过滤,如下所示:

{
    "size": 40,
    "query": {
      "bool": {
        "must": [
          {
            "match": {
              "name": {
                "query": "Salem Chennai",
                "fuzziness": 1,
                "prefix_length": 2,
                "operator": "or"
              }
            }
          }
        ],
        "filter": [
          {
            "term": {
              "country_name.keyword": "India"
            }
          }
        ]
      }
    }
  }

字段 country_name(没有 .keyword)在索引时被分析(标准化),因此根据您的分析器,它已被转换为其他内容(例如小写,可能是词干,...)。

【讨论】:

  • 谢谢,这行得通。如果我必须仅使用术语 country_name 进行过滤,是否应该对其进行不同的索引?
  • 要直接使用country_name,您需要查找“印度”(而不是印度)或在搜索查询中指定分析器(不适用于术语查询)。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 2020-11-10
  • 2020-11-09
  • 2021-11-04
  • 2020-10-11
  • 1970-01-01
相关资源
最近更新 更多