【问题标题】:how to do exact match in elasticsearch?如何在elasticsearch中进行精确匹配?
【发布时间】:2015-02-18 07:56:39
【问题描述】:

这里我给出了我更新的映射

curl -X PUT localhost:9200/testing/listings/_mapping -d '{
  "listings" : {
    "properties" : {
        "address" : {
           "properties": {
              "location": { "type" : "string",
                            "index" : "not_analyzed"
               }
            }
        },
        "suggest" : { "type" : "completion",
                      "index_analyzer" : "simple",
                      "search_analyzer" : "simple",
                      "payloads" : true
        }
      }
   }
}'

我的映射创建索引如下

{
  "testing": {
    "mappings": {
      "listings": {
        "properties": {
          "address": {
            "properties": {
              "city": {
                "type": "string"
              },
              "line1": {
                "type": "string"
              },
              "line2": {
                "type": "string"
              },
              "line3": {
                "type": "string"
              },
              "location": {
                "type": "string",
                "index": "not_analyzed"
              },
              "pincode": {
                "type": "string"
              }
            }
          },
          "title": {
            "type": "string"
          }
        }
      }
    }
  }
}

但我的数据仍然不匹配。

我的样本数据是

{
  "listings": {
    "title": "testing 3",
    "address": {
      "line1": "3rd cross",
      "line2": "6th main",
      "line3": "",
      "landmark": "",
      "location": "k r puram",
      "pincode": "",
      "city": "Bangalore"
    }
  }
}

当我以k r puram 给出查询时,我得到了匹配的结果。

但是当我以r r puramr k puram 进行查询时,我也得到了属于k r puram 的结果。

在上面的查询中,我只有k r puram 的列表,其他我没有列表,所以除了k r puram 它应该给出空结果。

这是我的查询:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "published": true
          }
        },
        {
          "match": {
            "inActive": false
          }
        },
        {
          "range": {
            "propertyDetailsCategory.build_up_area": {
              "lte": 200
            }
          }
        },
        {
          "match": {
            "type": "commercial"
          }
        },
        {
          "match": {
            "purpose": "rent"
          }
        },
        {
          "range": {
            "commercialsCategory.exp_rent": {
              "lte": 50000
            }
          }
        },
        {
          "match": {
            "address.location": "k r puram"
          }
        }
      ]
    }
  }
}

【问题讨论】:

  • 1.为什么只对单个字段使用 multi_match ? 2.“address.location”实际上包含什么? 3、如何分析?
  • 我也使用了匹配,那个时候也同样的结果来了。 address.location 包含位置,“address.location”是列表对象中的字段。 @OllyCruickshank
  • 让我重新表述我的问题 - “address.location”是否包含“k r puram”的确切值?
  • 是的,它包含 k r puram
  • 如果数据恰好是“k r puram”并且您正在搜索“k r puram” - 那么听起来您不需要分析仪。您是否在映射中将字段设置为“index”:“not_analyzed”?

标签: node.js mongodb indexing elasticsearch exact-match


【解决方案1】:

如果数据恰好是“k r puram”并且您正在搜索“k r puram” - 那么您不应该使用分析仪。

在 Elasticsearch 中插入数据时,默认行为是使用标准分析器。

要禁用此使用

 "index": "not_analyzed" 

在相应字段的映射中。


如果你的映射如下:

curl -XPOST http://localhost:9200/index/address/_mapping -d '
{"address": {
  "properties": { 
    "city": {"type": "string"}, 
    "line1": {"type": "string"}, 
    "line2": {"type": "string"}, 
    "line3": {"type": "string"}, 
    "location": { "type": "string", "index": "not_analyzed"}, 
    "pincode": {"type": "string"} 
 }}}'

那么你的数据必须匹配它,例如这不匹配它:

curl -XPOST http://localhost:9200/index/address/ -d '
{"title":"testing",
 "address":
      {"line1":"#51",
       "line2":"3rd cross",
       "line3":"6th main",
       "location":"k r puram",
       "pincode":"560041"}}

但是这确实匹配(我的修改):

curl -XPOST http://localhost:9200/index/address/ -d '
{"line1":"#51",
 "line2":"3rd cross",
 "line3":"6th main",
 "location":"k r puram",
 "pincode":"560041"}'

这个查询按预期找到了文档:

curl -XGET http://localhost:9200/index/address/_search -d '
{
   "query" :{"match" : {"location": "k r puram"}}
}'

如果您无法更改数据,则将额外级别添加到映射中,例如:

curl -XPOST http://localhost:9200/index/address3/_mapping -d '{
  "address3" : {
    "properties" : {
      "address" : {
        "properties" : {
          "city" : {
            "type" : "string"
          },
          "line1" : {
            "type" : "string"
          },
          "line2" : {
            "type" : "string"
          },
          "location" : {
            "type" : "string", "index": "not_analyzed"
          }
        }
      },
      "title" : {
        "type" : "string"
     }
   }
 }
}'

查询再次运行良好:

curl -XGET http://localhost:9200/index/address3/_search -d '
{
   "query" :{"match" : {"address.location": "k r puram"}}
}'

【讨论】:

  • 如果“index”设置为“not_analysed”,则elasticsearch不会根据空格分割文本,即整个文本将被视为单个标记。因此,在搜索期间将搜索完整的文本。另一个简单的解决方案是在索引之前用其他字符替换空格。例如:“k r puram” => k_r_puram。
  • @Olly 我修改后的映射是 curl -X PUT localhost:9200/testing/listings/_mapping -d '{ "listings" : { "properties" : { "address" : { "properties": {“位置”:{“类型”:“字符串”,“索引”:“未分析”}}},“建议”:{“类型”:“完成”,“索引分析器”:“简单”,“搜索分析器”: “简单”,“有效载荷”:真 } } } }'
  • 太棒了,成功了吗?如果可以,你能接受我的回答吗?
  • 不,它没有给出任何位置的单一结果@OllyCruickshank
  • 您可以在您的问题中添加一些示例数据吗?
【解决方案2】:

你试过吗? (使用 .raw 子字段来匹配“未标记化”值的值)

{"query":{
   "bool":{
      "must":[
       {"match":{"published":true}},
       {"match":{"inActive":false}},
       {"range":{"propertyDetailsCategory.build_up_area":{"lte":200}}},
       {"match":{"type":"commercial"}},
       {"match":{"purpose":"rent"}},
       {"range":{"commercialsCategory.exp_rent":{"lte":50000}}},
       {"match":{"address.location.raw": "k r puram"}}
     ]
   }
 }
}

尝试在您的旧地图上使用此查询,它应该可以工作:)

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2013-03-10
    • 2013-02-02
    相关资源
    最近更新 更多