Piotr Pradzynski
Piotr Pradzynski

Reputation: 4535

Full-text search in date field with Elasticsearch

I have expiration_date date field in my Elasticsearch and request from user to be able to "full-text" search in this field and I have only one input for this.

So my initial mapping is:

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "expiration_date": {
          "type": "date"
        }
      }
    }
  }
}

and as a value I have for example: 2021-08-27T10:48:00.293Z.

User would like be able to search this by 2021, 2021-08, 2021-08-27, 27-08-2021 and 08-2021. For all this search terms I have only one input field which is used to search in other fields as well (fields like title, description etc.).

My idea to achieve this was to introduce some multi-fields to the base field. So something like:

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "expiration_date": {
          "type": "date",
          "fields": {
            "yyyy-mm-dd" : {
              //what to do here?
            },
            "yyyy-mm" : {
              //what to do here?
            },
            "yyyy" : {
              //what to do here?
            },
            "mm-yyyy" : {
              //what to do here?
            },
            "dd-mm-yyyy" : {
              //what to do here?
            }
          }
        }
      }
    }
  }
}

But I'm wondering if this is doable this way? Is something similar doable in any way only at the Elasticsearch side? Or I should rather prepare something similar on my application side, send it to ES and just use it there?

Upvotes: 3

Views: 671

Answers (1)

m0nhawk
m0nhawk

Reputation: 24238

Probably, the best solution would be to use the custom formats for date field in Elasticsearch:

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "expiration_date": {
          "type": "date",
          "format": "year||year_month||year_month_day||dd-MM-yyyy||MM-yyyy||strict_date_optional_time||epoch_millis"
        }
      }
    }
  }
}

Then you can range query the field:

{
  "query": {
    "bool": {
      "must": [{
        "range": {
          "expiration_date": {
            "gte": "27-01-2001"
          }
        }
      }]
    }
  }
}

Where you can use any format specified in mapping.

This solution would be the most scalable: you can just add more formats (available here or you can construct one) and reindex the data to support any new formats.

Upvotes: 1

Related Questions