我正在使用弹性搜索来索引和搜索位置,并且我遇到了一个按营业时间过滤的特定问题,我不知道如何解决
基本上,每个位置都会有营业时间(一周中的每一天),并且每天可能有超过 1 个“组”营业时间(我们现在使用 2 个)。
例如: 星期一:上午 9 点开门 / 中午 12 点关门 下午 1 点开门 / 晚上 9 点关门
给定当前时间和一周中的当前日期,我需要搜索“开放”位置。
我不知道如何将这些营业时间与位置详细信息一起索引,以及如何使用它们来过滤结果,任何帮助,建议将不胜感激
问候
我正在使用弹性搜索来索引和搜索位置,并且我遇到了一个按营业时间过滤的特定问题,我不知道如何解决
基本上,每个位置都会有营业时间(一周中的每一天),并且每天可能有超过 1 个“组”营业时间(我们现在使用 2 个)。
例如: 星期一:上午 9 点开门 / 中午 12 点关门 下午 1 点开门 / 晚上 9 点关门
给定当前时间和一周中的当前日期,我需要搜索“开放”位置。
我不知道如何将这些营业时间与位置详细信息一起索引,以及如何使用它们来过滤结果,任何帮助,建议将不胜感激
问候
更好的方法是使用nested
文档。
首先:设置您的映射以指定hours
文档应被视为嵌套:
curl -XPUT 'http://127.0.0.1:9200/foo/?pretty=1' -d '
{
"mappings" : {
"location" : {
"properties" : {
"hours" : {
"include_in_root" : 1,
"type" : "nested",
"properties" : {
"open" : {
"type" : "short"
},
"close" : {
"type" : "short"
},
"day" : {
"index" : "not_analyzed",
"type" : "string"
}
}
},
"name" : {
"type" : "string"
}
}
}
}
}
'
添加一些数据:(注意开放时间的多个值)
curl -XPOST 'http://127.0.0.1:9200/foo/location?pretty=1' -d '
{
"name" : "Test",
"hours" : [
{
"open" : 9,
"close" : 12,
"day" : "monday"
},
{
"open" : 13,
"close" : 17,
"day" : "monday"
}
]
}
'
然后运行查询,按当前日期和时间过滤:
curl -XGET 'http://127.0.0.1:9200/foo/location/_search?pretty=1' -d '
{
"query" : {
"filtered" : {
"query" : {
"text" : {
"name" : "test"
}
},
"filter" : {
"nested" : {
"path" : "hours",
"filter" : {
"and" : [
{
"term" : {
"hours.day" : "monday"
}
},
{
"range" : {
"hours.close" : {
"gte" : 10
}
}
},
{
"range" : {
"hours.open" : {
"lte" : 10
}
}
}
]
}
}
}
}
}
}
'
这应该有效。
不幸的是,在 0.17.5 中,它抛出了 NPE——它可能是一个简单的错误,很快就会修复。我在这里打开了一个问题:https ://github.com/elasticsearch/elasticsearch/issues/1263
更新奇怪的是,我现在无法复制 NPE - 这个查询似乎在 0.17.5 及更高版本上都能正常工作。一定是暂时的故障。
克林特
上述解决方案不起作用,因为如果您有一些在星期一 2-4 和星期二 6-8 开放的东西,那么在星期一 6 点进行过滤将返回文档。下面是一些伪json来说明它应该如何完成。
{
"business_document": "...",
"hours": {
"1": [
{
"open": 930,
"close": 1330
},
{
"open": 1530,
"close": 2130
}
],
"2": [
{
"open": 1000,
"close": 2100
}
],
"3": [
{
"open": 1000,
"close": 2100
}
],
"4": [
{
"open": 1000,
"close": 2100
}
],
"5": [
{
"open": 1000,
"close": 2100
}
],
"6": [
{
"open": 1000,
"close": 2100
}
],
"7": [
{
"open": 930,
"close": 1330
},
{
"open": 1530,
"close": 2130
}
]
}
}
Sample Filter (can be applied to any query for a businesses):
{
"filter": {
"and": [ //Must match all following clauses
{
"range": {
"hours.1.open": { //Close Hour of Day 1 (current day)
"lte": 1343 //Store open time is less than 13:43 (current time)
}
}
},
{
"range": {
"hours.1.close": { //Close Hour of Day 1 (current day)
"gte": 1343 //Store close time is greater than 13:43 (current time)
}
}
}
]
}
}
所有时间都应采用标准时区 (GMT) 的 24 小时格式
最简单的方法是在位置打开时命名和索引时间段。首先,您需要提出一个模式,为可以打开位置的每个时间段分配一个名称。例如,thu17 可能代表星期四下午 5 点。然后,您的示例中的位置应使用包含以下值的几个“open”字段进行索引:mon09、mon10、mon11、mon13、mon14、mon15、mon16、mon17、mon18、mon19、mon20、tue09、tue10 等。要仅显示周四上午 7 点开放的位置,您只需将此过滤器添加到您的查询中:open:thu07。
您不必使用这个特定的命名模式。例如,您可以只计算从一周开始的小时数。在这种情况下,周一上午 9 点将是 9 点,周一晚上 11 点 - 23 日,周二凌晨 2 点 - 26 日,依此类推。