ElasticSearch - 日期范围条件应与日期范围数组中的EXACTLY一个项目匹配 [英] ElasticSearch - date range condition should match EXACTLY one item from date range array
问题描述
其中
availabilty
是一个包含嵌套
对象(可用性
type是嵌套
)。 这些对象中的每一个都有日期范围,该公寓可用。
apartments = [
{
_id:kjty873yhekrg789e7r0n87e,
first_available_date :06,
可用性:[
{
开始:2016-06-21,
结束:2016 -08-01
},
{
开始:2016-08-20,
结束:2016-08-28
},
{
开始:2016-10-03,
结束:2016-11-02
},
{ //这意味着它只有一天可用。
开始:2016-11-13,
结束:2016-11-13
},
{
开始: 2016-11-28,
end:2017-01-14
}
],
apartment_metadata1:56456,
apartment_metadata2 :8989,
status:active
},
{
_id:hgk87783iii86937jh,
first_available_date: -09,
可用性:[
{
start:2016-06-09,
end:2016-07-02
},
{
开始:2016-07-21,
结束:2016-12-19
},
{
start:2016-12-12,
end:2017-07-02
}
],
apartment_metadata1 :23534,
apartment_metadata2:24377,
状态:活动
}
]
我想搜索可用于特定日期范围的公寓(例如 2016-8-20至2016-12-12
)。而
范围应该落在各种公寓的可用日期范围之内。
所以我想写一个查询,如:
{
查询:{
bool:{
必须:[
{
range:{first_available_date:{lte:08-8}},
match:{status:active}
},
过滤器:[
{
范围:
{
apartments.availability。开始:{gte:2016-08-20},
apartments.availability.end:{lte:2016-12-12}
}
}
]
}
}
}
以上查询将返回两个公寓(与MULTIPLE 可用性
匹配条件的对象),
并且这是不正确的,它应该只返回文档与 _id:hgk87783iii86937jh
就像可用性
对象与创建者匹配,即 {开始:2016-07-21,结束:2016-12 -19\" }
。因此,为了获得正确的结果,条件应该是 - 应该与公寓doc
中应该匹配的条件一致的可用性
对象。那么如何执行上述查询中应该有一个匹配呢?第二个问题 - 我的查询是否正确?
使用嵌套查询应该允许你实现上述。
使用内部命中获得匹配的可用性块
。
下面是一个实现这个的例子:
创建索引
put testindex
{
mappings:{
data:{
properties:{
:{
type:nested
}
}
}
}
}
索引数据
put testindex / data / 1
{
first_available_date:2016-06-21,
availability:[
{
开始:2016-06-21,
结束:2016-08-01
},
{
开始: 08-20,
end:2016-08-28
},
{
开始:2016-10-03,
end:2016-11-02
},
{
start:2016-11-13,
end:2016- 11-13
},
{
开始:2016-11-28,
结束:2017-01-14
},
{
开始:2016-07-21,
结束:2016-12-19
}
],
apartment_metadata1:4234,
apartment_metadata2:687878,
status:active
}
查询:
post testindex / data / _search
{
query:{
bool:{
must:[
{
范围:{
first_available_date:{
lte:2016-08-20
}
}
},
{
match:{
status:active
}
}
],
filter:[
{
嵌套:{
路径:可用性,
查询:{
bool:{
必须 :[
{
range:{
availability.start:{
lte:2016-08-20
}
},
{
range:{
availability.end:{
gte:2016-12-12
}
}
}
]
}
},
inner_hits:{}
}
}
]
}
}
}
结果:
hits:{
pre>
total:1,
max_score:1.4142135,
hits:[
{
_index:testindex,
_type:data,
_id:1,
_score:1.4142135,
_source:{
first_available_date:2016-06-21,
可用性:[
{
开始:2016-06-21,
结束:2016-08-01
},
{
开始: 08-20,
end:2016-08-28
},
{
开始:2016-10-03,
end:2016-11-02
},
{
start:2016-11-13,
end:2016- 11-13
},
{
开始:2016-11-28,
结束:2017-0 1-14
},
{
开始:2016-07-21,
结束:2016-12-19
],
apartment_metadata1:4234,
apartment_metadata2:687878,
status:active
},
inner_hits :{
可用性:{
hits:{
total:1,
max_score:1.4142135,
hits
{
_index:testindex,
_type:data,
_id:1,
_nested
field:可用性,
offset:5
},
_score:1.414 2135,
_source:{
start:2016-07-21,
end:2016-12-19
}
}
]
}
}
}
}
]
}
I am planning to store million of airbnb type apartments availabilty in elasticsearch . Where
availabilty
is an array that containsnested
objects (availability
type isnested
). And each of those objects have date range, in which that apartment is available.apartments = [ { "_id": "kjty873yhekrg789e7r0n87e", "first_available_date": "2016-06-21", "availability": [ { "start": "2016-06-21", "end": "2016-08-01" }, { "start": "2016-08-20", "end": "2016-08-28" }, { "start": "2016-10-03", "end": "2016-11-02" }, { //This means it is available only for one day. "start": "2016-11-13", "end": "2016-11-13" }, { "start": "2016-11-28", "end": "2017-01-14" } ], "apartment_metadata1": 56456, "apartment_metadata2": 8989, "status": "active" }, { "_id": "hgk87783iii86937jh", "first_available_date": "2016-06-09", "availability": [ { "start": "2016-06-09", "end": "2016-07-02" }, { "start": "2016-07-21", "end": "2016-12-19" }, { "start": "2016-12-12", "end": "2017-07-02" } ], "apartment_metadata1": 23534, "apartment_metadata2": 24377, "status": "active" } ]
I would want to search apartments those are available for a specific date range (say
2016-08-20 to 2016-12-12
). And that range should fall inside one of the availability date ranges of various apartments.So I want to write a query, something like:
{ "query": { "bool": { "must": [ { "range": { "first_available_date": {"lte": "2016-08-20"} }, "match": { "status": "active" } } ] }, "filter": [ { "range": { "apartments.availability.start": {"gte": "2016-08-20"}, "apartments.availability.end": {"lte": "2016-12-12"} } } ] } } }
And above query will return me both apartments (with MULTIPLE
availability
objects matching the condition), and that is incorrect, it should only return document with_id: hgk87783iii86937jh
as there is EXACTLY oneavailability
object matches the creiteria and that is{"start": "2016-07-21", "end": "2016-12-19"}
. So in order to have correct result, the condition should be - there should be EXACTLY oneavailability
object in apartment doc that should match the condition. So how to enforce that there should be EXACTLY one match in the above query? Second question - is my query even correct?解决方案Using nested query should allow you to achieve the above. Use inner-hits to get the
availability-block
that matched. Below is an example to implement this:Create Index
put testindex { "mappings": { "data" : { "properties": { "availability" : { "type": "nested" } } } } }
Index Data:
put testindex/data/1 { "first_available_date": "2016-06-21", "availability": [ { "start": "2016-06-21", "end": "2016-08-01" }, { "start": "2016-08-20", "end": "2016-08-28" }, { "start": "2016-10-03", "end": "2016-11-02" }, { "start": "2016-11-13", "end": "2016-11-13" }, { "start": "2016-11-28", "end": "2017-01-14" }, { "start": "2016-07-21", "end": "2016-12-19" } ], "apartment_metadata1": 4234, "apartment_metadata2": 687878, "status": "active" }
Query:
post testindex/data/_search { "query": { "bool": { "must": [ { "range": { "first_available_date": { "lte": "2016-08-20" } } }, { "match": { "status": "active" } } ], "filter": [ { "nested": { "path": "availability", "query": { "bool": { "must": [ { "range": { "availability.start": { "lte": "2016-08-20" } } }, { "range": { "availability.end": { "gte": "2016-12-12" } } } ] } }, "inner_hits": {} } } ] } } }
Results:
"hits": { "total": 1, "max_score": 1.4142135, "hits": [ { "_index": "testindex", "_type": "data", "_id": "1", "_score": 1.4142135, "_source": { "first_available_date": "2016-06-21", "availability": [ { "start": "2016-06-21", "end": "2016-08-01" }, { "start": "2016-08-20", "end": "2016-08-28" }, { "start": "2016-10-03", "end": "2016-11-02" }, { "start": "2016-11-13", "end": "2016-11-13" }, { "start": "2016-11-28", "end": "2017-01-14" }, { "start": "2016-07-21", "end": "2016-12-19" } ], "apartment_metadata1": 4234, "apartment_metadata2": 687878, "status": "active" }, "inner_hits": { "availability": { "hits": { "total": 1, "max_score": 1.4142135, "hits": [ { "_index": "testindex", "_type": "data", "_id": "1", "_nested": { "field": "availability", "offset": 5 }, "_score": 1.4142135, "_source": { "start": "2016-07-21", "end": "2016-12-19" } } ] } } } } ] }
这篇关于ElasticSearch - 日期范围条件应与日期范围数组中的EXACTLY一个项目匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!