通过弹性搜索/轮胎的时间表查找开放商店 [英] Find open Shops through Timetable with Elasticsearch/Tire

查看:119
本文介绍了通过弹性搜索/轮胎的时间表查找开放商店的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有模型商店每个都与时间表有关,可能包含以下内容:

  shop_id:1,day:5,open_hour:7,open_minutes:0,close_hour:13,close_minute:30 
shop_id:1,day :5,open_hour:14,open_minutes:30,close_hour:18,close_minute:00

code>时间表可以有更优雅的格式,但问题是下一个:如何使用elasticsearch(轮胎)可以找到开放的商店?



所有的想法都将被欣赏!谢谢!






找到解决方案:


  1. 每天创建单独的索引(星期日,星期一,..)


  2. 每天建立从时间表

     ((open_hour * 60 + open_minute)..(close_hour * 60 + close_minute))to_a 


  3. 添加过滤器进行搜索:

      filter:term,current_day_name => (current_hour * 60 + current_minutes)


但是它看起来很麻烦,因为如果 Shop 每天工作8小时,我创建了数组,大小为: 8 * 60 = 480 (它被转换为字符串作为索引字段),所以这就是为什么这个问题仍然是开放的,也许有人会找到更好的解决方案






@Andrei Stefan的轮胎部分答案:

 索引:open_hours,键入::嵌套do 
索引:打开,键入:'integer'
索引:关闭,键入:'integer'
end

open_hours_query = Tire :: Search :: Query。 new do
filtering do
query {all}
filter:range,open_hours.open=> {lte:current_time}
filter:range,open_hours.close=> {gte:current_time}
end
end

过滤器:嵌套,{path:'open_hours',查询:open_hours_query.to_hash}


解决方案

我会考虑像下面这样做:


  1. 开始和结束时间是Elasticsearch中嵌套对象数组的整数值:

示例:07:00开始营业,13:30结束,然后在14:30开放,第1天18:00结束将在ES中翻译成:

 shop_name:Shop 1,
open_hours:[
{open:420,close:810},
{open:870,close:1080}
]




  1. 本周(1 - > 7)中的每一天表示一个值(要添加到分钟数):





 第1天=添加0 
第2天=添加2000
第3天=添加4000
...
第7天=加10000

所以,每天增加2000,因为每天最多包含1440分钟(24小时* 60分钟),并且能够区分一天与单个号码,这些数字不必相交。



所以,上面的例子与店铺开放在07:00将翻译为第4天,例如:

 shop_name:Shop 1,
open_hours:[
{open:6420,close:6810},
{open:6870,close:7080}
]




  1. 查询这些文件时,你想搜索的那一天需要服从与上述相同的规则。例如,如果您想在13:45的第4天看到商店1是否打开,您将搜索(6000 + 13 * 60 + 45 = 6825)分钟。


  2. Elasticsearch中以上所有内容的映射将是:






  {
mappings:{
shop:{
properties:{
shop_name {type:string},
open_hours:{
type:nested,
properties:{
open类型:integer},
close:{type:integer}
}
}
}
}
}
}




  1. 测试数据: / li>





  POST / shops / shop / _bulk 
{index:{}}
{shop_name:Shop 1,open_hours:[{open:420,close:810},{open:870, :1080}]}
{index:{}}
{shop_name:Shop 2,open_hours:[{open:0,close:500} {OPE n:1000,close:1440}]}
{index:{}}
{shop_name:Shop 3,open_hours:[{open ,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:2580close:3000},{open:3100关闭:3440}]}
{index:{}}
{shop_name:Shop 6,open_hours:[{open:6000,close },{打开:6700,关闭:6900}]}




  1. 查询在第2天开始的商店,每天2400点(06:40):





  {
查询:{
bool:{
必须:[
{
nested:{
path:open_hours,
query:{
bool:{
must b $ b {
filtered:{
过滤器:{
范围:{
open_hours.open:{
lte:2400
}}}}},
{
filtered:{
filter:{
range:{
open_hours.close:{
gte:2400
} }}}}
]
}}}}
]
}}}

输出商店4和商店5:

 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
}
]


I have model Shop each has relation with Timetable which could contain something like:

shop_id: 1, day: 5, open_hour: 7,  open_minutes: 0,  close_hour: 13, close_minute: 30
shop_id: 1, day: 5, open_hour: 14, open_minutes: 30, close_hour: 18, close_minute: 00

of course Timetable could have more elegant format, but question is next: how with elasticsearch(tire) could I find Shop which is open?

all Idea will be apreciated! Thanks!


Found solution:

  1. create separate index for each day (sunday, monday, ..)

  2. for each day build full array of minutes from Timetable:

    ((open_hour * 60 + open_minute)..(close_hour * 60 + close_minute)).to_a
    

  3. add filter to search:

    filter :term, current_day_name => (current_hour * 60 + current_minutes)
    

this solution works as well, but it looks cumbersome, because if Shop works 8-h hours per day I have created array with size: 8 * 60 = 480 (which is converted to string as indexed field), so thats why this question is still open, and maybe someone will find better solution


Tire part for @Andrei Stefan answer:

indexes :open_hours, type: :nested do
  indexes :open, type: 'integer'
  indexes :close, type: 'integer'
end

open_hours_query = Tire::Search::Query.new do
  filtered do
    query { all }
    filter :range, "open_hours.open"   => { lte: current_time }
    filter :range, "open_hours.close"  => { gte: current_time }
  end
end

filter :nested, { path: 'open_hours', query: open_hours_query.to_hash }

解决方案

I would consider doing it like the following:

  1. The opening and closing hours are integer values of an array of nested objects in Elasticsearch:

Example: shop opening at 07:00 and closing at 13:30 and then opening at 14:30 and closing at 18:00 in day 1 would be translated to this in ES:

"shop_name": "Shop 1",
"open_hours": [
  { "open": 420, "close": 810 },
  { "open": 870, "close": 1080 }
]

  1. Each day in the week (1 -> 7) represents a value (to be 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 at most 1440 minutes (24 hours * 60 minutes) and to be able to differentiate one day from a single number these numbers don't have to intersect.

So, the example above with the shop opening at 07:00 would be translated for Day 4 for example to this:

"shop_name": "Shop 1",
"open_hours": [
  { "open": 6420, "close": 6810 },
  { "open": 6870, "close": 7080 }
]

  1. When querying these documents, that point of the day you want to search needs to obey the same rules as above. For example, if you want to see if in Day 4 at 13:45 the "Shop 1" is opened you would search for a (6000 + 13*60 + 45 = 6825) minute.

  2. The mapping for everything above in Elasticsearch would be this:

{
  "mappings": {
    "shop" : {
      "properties": {
        "shop_name" : { "type" : "string" },
        "open_hours" : {
          "type" : "nested",
          "properties": {
            "open" : { "type" : "integer" },
            "close": { "type" : "integer" }
          }
        }
      }
    }
  }
}

  1. Test 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}]}

  1. Querying for shops opened in Day 2 at 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
                          }}}}}
                ]
              }}}}
            ]
}}}

Would output Shop 4 and Shop 5:

         "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
              }
           ]

这篇关于通过弹性搜索/轮胎的时间表查找开放商店的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆