I would like to do it as follows:
- Opening and closing hours are integer values โโof an array of nested objects in Elasticsearch:
Example: opening a store at 07:00 and closing at 13:30, and then opening at 14:30 and closing at 18:00 on the 1st day will be transferred to this in ES:
"shop_name": "Shop 1", "open_hours": [ { "open": 420, "close": 810 }, { "open": 870, "close": 1080 } ]
- Each day of the week (1 โ 7) represents a value (which is added to the number of minutes):
Day 1 = addition 0 Day 2 = addition 2000 Day 3 = addition 4000 ... Day 7 = addition 10000
So, for each day there is an increment of 2000, because each day contains no more than 1440 minutes (24 hours * 60 minutes) and in order to distinguish one day from one number, these numbers should not intersect.
So, the example above with the opening of the store at 07:00 will be translated for the 4th day, for example:
"shop_name": "Shop 1", "open_hours": [ { "open": 6420, "close": 6810 }, { "open": 6870, "close": 7080 } ]
When requesting these documents, the point of the day that you want to find must obey the same rules as above. For example, if you want to see whether โShop 1โ is open on day 4 at 13:45, you will look for a minute (6000 + 13 * 60 + 45 = 6825).
The mapping for everything above in Elasticsearch will be as follows:
{ "mappings": { "shop" : { "properties": { "shop_name" : { "type" : "string" }, "open_hours" : { "type" : "nested", "properties": { "open" : { "type" : "integer" }, "close": { "type" : "integer" } } } } } } }
- Testing data:
POST /shops/shop/_bulk {"index":{}} {"shop_name":"Shop 1","open_hours":[{"open":420,"close":810},{"open":870,"close":1080}]} {"index":{}} {"shop_name":"Shop 2","open_hours":[{"open":0,"close":500},{"open":1000,"close":1440}]} {"index":{}} {"shop_name":"Shop 3","open_hours":[{"open":0,"close":10},{"open":70,"close":450},{"open":900,"close":1050}]} {"index":{}} {"shop_name":"Shop 4","open_hours":[{"open":2000,"close":2480}]} {"index":{}} {"shop_name":"Shop 5","open_hours":[{"open":2220,"close":2480},{"open":2580,"close":3000},{"open":3100,"close":3440}]} {"index":{}} {"shop_name":"Shop 6","open_hours":[{"open":6000,"close":6010},{"open":6700,"close":6900}]}
- Request for stores open on Day 2 per minute # 2400 of the day (06:40):
{ "query": { "bool": { "must": [ { "nested": { "path": "open_hours", "query": { "bool": { "must": [ { "filtered": { "filter": { "range": { "open_hours.open": { "lte": 2400 }}}}}, { "filtered": { "filter": { "range": { "open_hours.close": { "gte": 2400 }}}}} ] }}}} ] }}}
Store 4 and Store 5 will be displayed:
"shop_name": "Shop 4", "open_hours": [ { "open": 2000, "close": 2480 } ] "shop_name": "Shop 5", "open_hours": [ { "open": 2220, "close": 2480 }, { "open": 2580, "close": 3000 }, { "open": 3100, "close": 3440 } ]