how to do exact match in elasticsearch?

1.7k views Asked by At

Here I have given my updated mapping

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

my mapping is created index as follows

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

but still my data is not matching.

my sample data is

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

when I give the query as k r puram I am getting the matched results.

But when I am giving the query as r r puram or r k puram that time also I am getting the results which is belongs to k r puram.

In above query I am having listings only for k r puram others I don't have listings so other than k r puram it should give the empty results.

this is my query:

{
  "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"
          }
        }
      ]
    }
  }
}
2

There are 2 answers

8
Olly Cruickshank On BEST ANSWER

If the data is exactly "k r puram" and you're searching for exactly "k r puram" - then you shouldn't use an analyser.

When inserting data the default behaviour in Elasticsearch is to use the standard analyser.

To disable this use

 "index": "not_analyzed" 

in the mapping for the appropriate field.


if your mapping is as follows:

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

then your data must match it, for example this doesn't match it:

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

This however does match (my modifications):

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

And this query finds the document as expected:

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

if you can't change your data, then add the extra level to the mapping,e.g.:

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

Again the query works well:

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

Have you tried this? (use .raw sub field to match value on "not tokenized" value)

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

Try to use this query on your old mapping, it should work :)