I originally asked this question on StackOverflow, but haven't found a satisfactory answer yet:
Suppose I have an index with multiple fields of type text
and one or more of type date
(of some format, say yyyy/MM/dd
). If I want to enable users to perform queries using only a single input field (so, Google-like), how should I go about supporting the date
fields? The text
fields, so far, are mainly queried using the simple_query_string
and multi_match
queries.
Now, the simple_query_string
works fine as long as an entire date
in the correct format is searched. But if, for instance, I want to filter by year, the missing fields are automatically filled with the smallest accepted value (so e.g. for months it's 01
).
Here's the approaches I've tried so far:
- split the components of a
date
field into year, month etc. This however, as far as I can make out, requires anupdate_by_query
, while having this rule at index time would be much nicer... - use
range
query. The available formatting however does not support the level of freedom the user input should have (so something like2000 <some-name>
would not be accepted... - copy the value as date to a different field and accept more formats -> doesn't work like that...
What my next approaches could be:
- define an analyzer that splits dates by available delimiters and index everything as text and query as text. This should probably work, but elegant it is not...
- change the logstash pipeline to write the date components to different fields. However, it feels like this should be possible to do in Elasticsearch itself...
Anyone had to solve this specific problem before? Thanks for suggestions!
Update:
What works is doing the update_by_query
to extract the desired fields, like so
POST date_test/_update_by_query
{
"script": {
"source": """
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ldt = LocalDate.parse(ctx._source.GEBURTSDATUM, formatter);
ctx._source.GEBURTSJAHR = ldt.getYear();
ctx._source.GEBURTSMONAT = ldt.getMonthValue();
ctx._source.GEBURTSTAG = ldt.getDayOfMonth();
"""
}
}
Could this be translated into an index mapping instead of using the update
api?