Darshan Mehta
Darshan Mehta

Reputation: 30839

Elasticsearch multiple values match without analyzer

Pardon my knowledge on ElasticSearch. I have an Elasticsearch collection which has documents like these:

{
    "date": "2013-12-30T00:00:00.000Z",
    "value": 2,
    "dimensions": {
        "region": "Coimbra District"

    }
}
{
    "date": "2013-12-30T00:00:00.000Z",
    "value": 1,
    "dimensions": {
        "region": "Federal District"        
    }
}
{
    "date": "2013-12-30T00:00:00.000Z",
    "value": 1,
    "dimensions": {
        "region": "Masovian Voivodeship"
    }
}

These 3 json documents are indexed in the ES server. I haven't provided any analyzer type (and don't know how to provide one either :)) I am using spring data Elasticsearch and executing the following query to search for the docs with region 'Masovian Voivodeship' or 'Federal District':

{
  "query_string" : {
    "query" : "Masovian Voivodeship OR Federal District",
    "fields" : [ "dimensions.region" ]
  }
}

I am expecting it to return 2 hits. However, it returns all 3 docs (probably due to 3rd one having district in it). How can I modify the query so that it can perform the EXACT match and only provide 2 documents? I am using following method:

QueryBuilders.queryString(<OR string>).field("dimensions.region")

I have tried QueryBuilders.termsQuery, QueryBuilders.inQuery and QueryBuilders.matchQuery (with array) but no luck.

Can anyone please help? Thanks in advance.

Upvotes: 3

Views: 1104

Answers (1)

Sloan Ahrens
Sloan Ahrens

Reputation: 8718

There are a couple of things you can do here.

To start, I set up an index without any explicit mapping or analysis, which means the standard analyzer will be used. That's important since it determines how we can query against the text fields.

So I started with:

DELETE /test_index

PUT /test_index
{
   "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 0
   }
}

PUT /test_index/doc/1
{
    "date": "2013-12-30T00:00:00.000Z",
    "value": 2,
    "dimensions": {
        "region": "Coimbra District"

    }
}

PUT /test_index/doc/2
{
    "date": "2013-12-30T00:00:00.000Z",
    "value": 1,
    "dimensions": {
        "region": "Federal District"        
    }
}

PUT /test_index/doc/3
{
    "date": "2013-12-30T00:00:00.000Z",
    "value": 1,
    "dimensions": {
        "region": "Masovian Voivodeship"
    }
}

Then I tried your query and got no hits. I don't understand why you have "dimensions.ga:region" in your fields parameter, but when I changed it to "dimensions.region" I got some results:

POST /test_index/doc/_search
{
   "query": {
      "query_string": {
         "query": "Masovian Voivodeship OR Federal District",
         "fields": [
            "dimensions.region"
         ]
      }
   }
}
...
{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 3,
      "max_score": 0.46911472,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "3",
            "_score": 0.46911472,
            "_source": {
               "date": "2013-12-30T00:00:00.000Z",
               "value": 1,
               "dimensions": {
                  "region": "Masovian Voivodeship"
               }
            }
         },
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "2",
            "_score": 0.3533006,
            "_source": {
               "date": "2013-12-30T00:00:00.000Z",
               "value": 1,
               "dimensions": {
                  "region": "Federal District"
               }
            }
         },
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 0.05937162,
            "_source": {
               "date": "2013-12-30T00:00:00.000Z",
               "value": 2,
               "dimensions": {
                  "region": "Coimbra District"
               }
            }
         }
      ]
   }
}

However, this returns a result you don't want. One way to fix that is as follows:

POST /test_index/doc/_search
{
   "query": {
      "query_string": {
         "query": "(Masovian AND Voivodeship) OR (Federal AND District)",
         "fields": [
            "dimensions.region"
         ]
      }
   }
}
...
{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 2,
      "max_score": 0.46911472,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "3",
            "_score": 0.46911472,
            "_source": {
               "date": "2013-12-30T00:00:00.000Z",
               "value": 1,
               "dimensions": {
                  "region": "Masovian Voivodeship"
               }
            }
         },
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "2",
            "_score": 0.3533006,
            "_source": {
               "date": "2013-12-30T00:00:00.000Z",
               "value": 1,
               "dimensions": {
                  "region": "Federal District"
               }
            }
         }
      ]
   }
}

Another way would to do it (I like this one better) which gives the same results is to use a combination of match query and boolean should:

POST /test_index/doc/_search
{
   "query": {
      "bool": {
         "should": [
            {
               "match": {
                  "dimensions.region": {
                     "query": "Masovian Voivodeship",
                     "operator": "and"
                  }
               }
            },
            {
               "match": {
                  "dimensions.region": {
                     "query": "Federal District",
                     "operator": "and"
                  }
               }
            }
         ]
      }
   }
}

Here is the code I used:

http://sense.qbox.io/gist/bb5062a635c4f9519a411fdd3c8540eae8bdfd51

Upvotes: 3

Related Questions