Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 494
Piotr Pradzynski Avatar asked Dec 27 '25 22:12

Piotr Pradzynski


1 Answers

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.

like image 108
m0nhawk Avatar answered Dec 30 '25 22:12

m0nhawk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!