如何在弹性搜索(aws)中存储日期范围数据并搜索范围?
How to store date range data in elastic search (aws) and search for a range?
我正在尝试在 elasticsearch 中存储酒店房间可用性。然后我需要
搜索从一个日期到另一个日期可用的房间。我想出了
存储数据可用性的两种方式,它们如下:
此处可用性字典存储所有日期和每个日期键的值是真还是假,表示其可用时间
那天与否。
{
"_id": "khg2uo47tyhgjwebu7624787",
"room_type": "garden view",
"hotel_name": "Cool hotel",
"hotel_id": "jytu64r982u0299023",
"room_metadata1": 233,
"room_color": "black",
"availability": {
"2016-07-01": true,
"2016-07-02": true,
"2016-07-03": false,
"2016-07-04": true,
"2016-07-05": true,
"2016-07-06": null,
"2016-07-07": true,
"2016-07-08": true,
----
----
for 365 days
}
}
此处可用性数组只存储有空房间的日期
{
"_id": "khg2uo47tyhgjwebu7624787",
"room_type": "garden view",
"hotel_name": "Cool hotel",
"hotel_id": "jytu64r982u0299023",
"room_metadata1": 535,
"room_color": "black",
"availability": ["2016-07-01", "2016-07-02", "2016-07-04", "2016-07-05", "2016-07-07", "2016-07-08"] ---for 365 days
}
}
我想搜索所有房间,这些房间从 from_date
到 to_date
可用,应该查看 availability
字典或 array.And 我的日期范围可能会扩大到 365 天
如何存储这些可用性数据,以便我可以轻松地执行上述搜索?
而且我找不到任何方法来搜索日期范围,所以有什么建议吗?
请注意,项目
在 availability
中可能无法保持排序。我可能有超过 1 亿条记录要搜索。
一种建模方法是使用 parent/child 文档。房间文档将是父文档,可用性文档将是它们的子文档。对于每个房间,每个房间可用的日期都会有一份可用性文档。然后,在查询时,我们可以查询在搜索间隔中每个日期(甚至不相交的日期)都有一个可用性子文档的父房间。
请注意,您需要确保在预订房间后立即删除每个预订日期的相应子文档。
让我们试试这个。首先创建索引:
PUT /rooms
{
"mappings": {
"room": {
"properties": {
"room_num": {
"type": "integer"
}
}
},
"availability": {
"_parent": {
"type": "room"
},
"properties": {
"date": {
"type": "date",
"format": "date"
},
"available": {
"type": "boolean"
}
}
}
}
}
然后添加一些数据
POST /rooms/_bulk
{"_index": { "_type": "room", "_id": 233}}
{"room_num": 233}
{"_index": { "_type": "availability", "_id": "20160701", "_parent": 233}}
{"date": "2016-07-01"}
{"_index": { "_type": "availability", "_id": "20160702", "_parent": 233}}
{"date": "2016-07-02"}
{"_index": { "_type": "availability", "_id": "20160704", "_parent": 233}}
{"date": "2016-07-04"}
{"_index": { "_type": "availability", "_id": "20160705", "_parent": 233}}
{"date": "2016-07-05"}
{"_index": { "_type": "availability", "_id": "20160707", "_parent": 233}}
{"date": "2016-07-07"}
{"_index": { "_type": "availability", "_id": "20160708", "_parent": 233}}
{"date": "2016-07-08"}
终于可以开始查询了。首先,假设我们要查找 2016-07-01
:
上可用的房间
POST /rooms/room/_search
{
"query": {
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
}
}
=> result: room 233
然后,让我们尝试搜索 2016-07-01
到 2016-07-03
之间可用的房间
POST /rooms/room/_search
{
"query": {
"bool": {
"minimum_should_match": 3,
"should": [
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-02"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-03"
}
}
}
}
]
}
}
}
=> Result: No rooms
但是,搜索从 2016-07-01
到 2016-07-02
的可用房间确实会找到 233
房间
POST /rooms/room/_search
{
"query": {
"bool": {
"minimum_should_match": 2,
"should": [
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-02"
}
}
}
}
]
}
}
}
=> Result: Room 233
我们还可以搜索不相交的区间,比如从 2016-07-01
到 2016-07-02
+ 从 2016-07-04
到 2016-07-05
POST /rooms/room/_search
{
"query": {
"bool": {
"minimum_should_match": 4,
"should": [
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-02"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-04"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-05"
}
}
}
}
]
}
}
}
=> Result: Room 233
等等...关键是要为每个您需要检查可用性的日期添加一个 has_child
查询,并将 minimum_should_match
设置为您要检查的日期数。
更新
另一种选择是使用 script
filter,但是对于 1 亿个文档,我不确定它是否可以很好地扩展。
在这种情况下,您可以保留原始设计(最好是第二个,因为使用第一个,您会在映射中创建太多不必要的字段),查询将如下所示:
POST /rooms/room/_search
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"inline": "def dates = doc.availability.sort(false); from = Date.parse('yyyy-MM-dd', from); to = Date.parse('yyyy-MM-dd', to); def days = to - from; def fromIndex = doc.availability.values.indexOf(from.time); def toIndex = doc.availability.values.indexOf(to.time); return days == (toIndex - fromIndex)",
"params": {
"from": "2016-07-01",
"to": "2016-07-04"
}
}
}
}
}
}
}
我是新手,刚刚学习 ES。这个 setup/mapping 有什么缺点?
再见..remco
我正在尝试在 elasticsearch 中存储酒店房间可用性。然后我需要 搜索从一个日期到另一个日期可用的房间。我想出了 存储数据可用性的两种方式,它们如下:
此处可用性字典存储所有日期和每个日期键的值是真还是假,表示其可用时间 那天与否。
{
"_id": "khg2uo47tyhgjwebu7624787",
"room_type": "garden view",
"hotel_name": "Cool hotel",
"hotel_id": "jytu64r982u0299023",
"room_metadata1": 233,
"room_color": "black",
"availability": {
"2016-07-01": true,
"2016-07-02": true,
"2016-07-03": false,
"2016-07-04": true,
"2016-07-05": true,
"2016-07-06": null,
"2016-07-07": true,
"2016-07-08": true,
----
----
for 365 days
}
}
此处可用性数组只存储有空房间的日期
{
"_id": "khg2uo47tyhgjwebu7624787",
"room_type": "garden view",
"hotel_name": "Cool hotel",
"hotel_id": "jytu64r982u0299023",
"room_metadata1": 535,
"room_color": "black",
"availability": ["2016-07-01", "2016-07-02", "2016-07-04", "2016-07-05", "2016-07-07", "2016-07-08"] ---for 365 days
}
}
我想搜索所有房间,这些房间从 from_date
到 to_date
可用,应该查看 availability
字典或 array.And 我的日期范围可能会扩大到 365 天
如何存储这些可用性数据,以便我可以轻松地执行上述搜索? 而且我找不到任何方法来搜索日期范围,所以有什么建议吗?
请注意,项目
在 availability
中可能无法保持排序。我可能有超过 1 亿条记录要搜索。
一种建模方法是使用 parent/child 文档。房间文档将是父文档,可用性文档将是它们的子文档。对于每个房间,每个房间可用的日期都会有一份可用性文档。然后,在查询时,我们可以查询在搜索间隔中每个日期(甚至不相交的日期)都有一个可用性子文档的父房间。
请注意,您需要确保在预订房间后立即删除每个预订日期的相应子文档。
让我们试试这个。首先创建索引:
PUT /rooms
{
"mappings": {
"room": {
"properties": {
"room_num": {
"type": "integer"
}
}
},
"availability": {
"_parent": {
"type": "room"
},
"properties": {
"date": {
"type": "date",
"format": "date"
},
"available": {
"type": "boolean"
}
}
}
}
}
然后添加一些数据
POST /rooms/_bulk
{"_index": { "_type": "room", "_id": 233}}
{"room_num": 233}
{"_index": { "_type": "availability", "_id": "20160701", "_parent": 233}}
{"date": "2016-07-01"}
{"_index": { "_type": "availability", "_id": "20160702", "_parent": 233}}
{"date": "2016-07-02"}
{"_index": { "_type": "availability", "_id": "20160704", "_parent": 233}}
{"date": "2016-07-04"}
{"_index": { "_type": "availability", "_id": "20160705", "_parent": 233}}
{"date": "2016-07-05"}
{"_index": { "_type": "availability", "_id": "20160707", "_parent": 233}}
{"date": "2016-07-07"}
{"_index": { "_type": "availability", "_id": "20160708", "_parent": 233}}
{"date": "2016-07-08"}
终于可以开始查询了。首先,假设我们要查找 2016-07-01
:
POST /rooms/room/_search
{
"query": {
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
}
}
=> result: room 233
然后,让我们尝试搜索 2016-07-01
到 2016-07-03
POST /rooms/room/_search
{
"query": {
"bool": {
"minimum_should_match": 3,
"should": [
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-02"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-03"
}
}
}
}
]
}
}
}
=> Result: No rooms
但是,搜索从 2016-07-01
到 2016-07-02
的可用房间确实会找到 233
POST /rooms/room/_search
{
"query": {
"bool": {
"minimum_should_match": 2,
"should": [
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-02"
}
}
}
}
]
}
}
}
=> Result: Room 233
我们还可以搜索不相交的区间,比如从 2016-07-01
到 2016-07-02
+ 从 2016-07-04
到 2016-07-05
POST /rooms/room/_search
{
"query": {
"bool": {
"minimum_should_match": 4,
"should": [
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-01"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-02"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-04"
}
}
}
},
{
"has_child": {
"type": "availability",
"query": {
"term": {
"date": "2016-07-05"
}
}
}
}
]
}
}
}
=> Result: Room 233
等等...关键是要为每个您需要检查可用性的日期添加一个 has_child
查询,并将 minimum_should_match
设置为您要检查的日期数。
更新
另一种选择是使用 script
filter,但是对于 1 亿个文档,我不确定它是否可以很好地扩展。
在这种情况下,您可以保留原始设计(最好是第二个,因为使用第一个,您会在映射中创建太多不必要的字段),查询将如下所示:
POST /rooms/room/_search
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"inline": "def dates = doc.availability.sort(false); from = Date.parse('yyyy-MM-dd', from); to = Date.parse('yyyy-MM-dd', to); def days = to - from; def fromIndex = doc.availability.values.indexOf(from.time); def toIndex = doc.availability.values.indexOf(to.time); return days == (toIndex - fromIndex)",
"params": {
"from": "2016-07-01",
"to": "2016-07-04"
}
}
}
}
}
}
}
我是新手,刚刚学习 ES。这个 setup/mapping 有什么缺点?
再见..remco