5

我正在使用弹性搜索来索引和搜索位置,并且我遇到了一个按营业时间过滤的特定问题,我不知道如何解决

基本上,每个位置都会有营业时间(一周中的每一天),并且每天可能有超过 1 个“组”营业时间(我们现在使用 2 个)。

例如: 星期一:上午 9 点开门 / 中午 12 点关门 下午 1 点开门 / 晚上 9 点关门

给定当前时间和一周中的当前日期,我需要搜索“开放”位置。

我不知道如何将这些营业时间与位置详细信息一起索引,以及如何使用它们来过滤结果,任何帮助,建议将不胜感激

问候

4

3 回答 3

4

更好的方法是使用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 及更高版本上都能正常工作。一定是暂时的故障。

克林特

于 2011-08-19T08:04:06.287 回答
2

上述解决方案不起作用,因为如果您有一些在星期一 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 小时格式

于 2014-10-16T02:19:15.157 回答
0

最简单的方法是在位置打开时命名和索引时间段。首先,您需要提出一个模式,为可以打开位置的每个时间段分配一个名称。例如,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 日,依此类推。

于 2011-08-18T11:29:12.243 回答