IS0*_*S04 6 ruby-on-rails elasticsearch tire
我有模型Shop每个都有关系Timetable,可能包含如下内容:
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
Run Code Online (Sandbox Code Playgroud)
当然Timetable可以有更优雅的格式,但问题是下一个:如何使用elasticsearch(轮胎)我可以找到开放的商店?
所有的想法都会被贬低!谢谢!
找到解决方案
为每一天创建单独的索引(星期日,星期一,...)
从每一天构建完整的分钟数Timetable:
((open_hour * 60 + open_minute)..(close_hour * 60 + close_minute)).to_a
Run Code Online (Sandbox Code Playgroud)添加过滤器进行搜索:
filter :term, current_day_name => (current_hour * 60 + current_minutes)
Run Code Online (Sandbox Code Playgroud)这个解决方案也可以,但它看起来很麻烦,因为如果Shop每天工作8小时我创建了大小的数组:( 8 * 60 = 480它被转换为字符串作为索引字段),这就是为什么这个问题仍然是开放的,也许是某人会找到更好的解决方案
@Andrei Stefan的轮胎部分回答:
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 }
Run Code Online (Sandbox Code Playgroud)
And*_*fan 12
我会考虑这样做:
例如:商店在07:00开业,在13:30关闭,然后在14:30开业,第1天在18:00关闭,将转换为ES:
"shop_name": "Shop 1",
"open_hours": [
{ "open": 420, "close": 810 },
{ "open": 870, "close": 1080 }
]
Run Code Online (Sandbox Code Playgroud)
Day 1 = addition 0
Day 2 = addition 2000
Day 3 = addition 4000
...
Day 7 = addition 10000
Run Code Online (Sandbox Code Playgroud)
因此,每天增加2000,因为每天最多包含1440分钟(24小时*60分钟),并且能够将一天与单个数字区分开,这些数字不必相交.
因此,上面的示例在07:00开店将在第4天翻译为例如:
"shop_name": "Shop 1",
"open_hours": [
{ "open": 6420, "close": 6810 },
{ "open": 6870, "close": 7080 }
]
Run Code Online (Sandbox Code Playgroud)
查询这些文档时,您想要搜索的那一天需要遵守与上述相同的规则.例如,如果您想在第4天13:45看到"商店1"打开,您将搜索(6000 + 13*60 + 45 = 6825)分钟.
Elasticsearch中上面所有内容的映射都是这样的:
{
"mappings": {
"shop" : {
"properties": {
"shop_name" : { "type" : "string" },
"open_hours" : {
"type" : "nested",
"properties": {
"open" : { "type" : "integer" },
"close": { "type" : "integer" }
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
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}]}
Run Code Online (Sandbox Code Playgroud)
{
"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
}}}}}
]
}}}}
]
}}}
Run Code Online (Sandbox Code Playgroud)
将输出Shop 4和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
}
]
Run Code Online (Sandbox Code Playgroud)
LATER EDIT:自从我添加了这个回复并且从那时起许多事情发生了变化以来,Elasticsearch已经采用了一种方式,filtered过滤器(在bool must我使用的上下文中)可以被一个bool filter甚至一个简单的替换must.此外,string6.x中不再存在,因此text如果您需要使用分析器或keyword("shop_name" : { "type" : "text" },)按商店名称进行搜索,则可以使用:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "open_hours",
"query": {
"bool": {
"filter": [
{
"range": {
"open_hours.open": {
"lte": 2400
}
}
},
{
"range": {
"open_hours.close": {
"gte": 2400
}
}
}
]
}
}
}
}
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
876 次 |
| 最近记录: |