Suraj Dalvi
Suraj Dalvi

Reputation: 1088

ElasticSearch Range query

I have created the index by using the following mapping:

put test1
{
    "mappings": {
        "type1": {
            "properties": {
                "age": {
                    "type": "text",
                    "fields": {
                        "raw": {
                            "type": "keyword",
                            "ignore_above": 32766
                        }
                    }
                }
            }
        }
    }
}

Added following documents into index:

PUT test1/type1/1/_create
{
  "age":50
}

PUT test1/type1/2/_create
{
  "age":100
}

PUT test1/type1/3/_create
{
  "age":150
}

PUT test1/type1/4/_create
{
  "age":200
}

I have used the following range query to fetch result:

GET test1/_search
{
    "query": {
        "range" : {
            "age" : {
                "lte" : 150
            }
        }
    }
}

It is giving me the following response :

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "test1",
        "_type": "type1",
        "_id": "2",
        "_score": 1,
        "_source": {
          "age": 100
        }
      },
      {
        "_index": "test1",
        "_type": "type1",
        "_id": "3",
        "_score": 1,
        "_source": {
          "age": 150
        }
      }
    ]
  }
}

the above response not showing document having age is 50 it is showing only age is 100 and 150. As 50 also less than 200. What is wrong here? Can anyone help me to get a valid result? In my schema age field type text, I don't want to change it.

How can I get a valid result?

Upvotes: 0

Views: 400

Answers (3)

รยקคгรђשค
รยקคгรђשค

Reputation: 1979

UPDATE: Tested on local system and it is working.

NOTE: Ideally, you would want the mappings to be correct, but if there is no other choice and you are not the person to decide on the mapping then you can still achieve it by following.

For ES version 6.3 onwards, try this.

 GET test1/type1/_search
    {
        "query": {
            "bool" : {
                "must" : {
                    "script" : {
                        "script" : {
                            "source": "Integer.parseInt(doc['age.raw'].value) <= 150",
                            "lang": "painless"
                         }
                    }
                }
            }
        }
    }

Sources to refer:

https://www.elastic.co/guide/en/elasticsearch/reference/6.3/query-dsl-script-query.html

https://discuss.elastic.co/t/painscript-script-cast-string-as-int/97034

Upvotes: 1

nitzien
nitzien

Reputation: 1267

Type for your field age in mapping is set to text. That is reason it is doing dictionary sorting where 50 > 150. Please use long data type. https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html

Upvotes: 0

banuj
banuj

Reputation: 3240

Because age field type is text, the range query is using alphabetically order. So the results are correct:

  • "100"<"150"
  • "150"="150"
  • "50">"150"

If you are ingesting only numbers in age field, you should change the age field type to number, or add another inner field as number, just you did with raw inner field.

Upvotes: 2

Related Questions