获取可用的公寓查询
Get available apartments query
概览
我有预订的公寓。我的索引有 嵌套字段 的保留,日期字段为 start_date 和 end_date。
我正在使用耐嚼的 ruby gem - 但我认为此时这并不重要。只需要让我的查询正确。
目标
我想获取在给定日期没有预订或根本没有预订的所有可用公寓。
当前查询
很遗憾returns所有公寓:
:query => {
:bool => {
:must_not => [
{
:range => {:"reservations.start_date" => {:gte => "2017-02-10"}}
},
{
:range => {:"reservations.end_date" => {:lte => "2017-02-12"}}
}
]
}
}
索引设置
{
"apartments" : {
"aliases" : { },
"mappings" : {
"apartment" : {
"properties" : {
"city" : {
"type" : "string"
},
"coordinates" : {
"type" : "geo_point"
},
"email" : {
"type" : "string"
},
"reservations" : {
"type" : "nested",
"properties" : {
"end_date" : {
"type" : "date",
"format" : "yyyy-MM-dd"
},
"start_date" : {
"type" : "date",
"format" : "yyyy-MM-dd"
}
}
},
"street" : {
"type" : "string"
},
"zip" : {
"type" : "string"
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1487289727161",
"number_of_shards" : "5",
"number_of_replicas" : "1",
"uuid" : "-rM79OUvQ3qkkLJmQCsoCg",
"version" : {
"created" : "2040499"
}
}
},
"warmers" : { }
}
}
首先,我认为你必须使用nested query。
我不熟悉 chewy-gem 但查询看起来像这样:
:query => {
:nested: => {
:path: => "reservations",
:query => {
:bool => {
:must_not => [
{
:range => {:"reservations.start_date" => {:gte => "2017-02-10"}}
},
{
:range => {:"reservations.end_date" => {:lte => "2017-02-12"}}
}
]
}
}
}
}
但它也可能无法正常工作,因为如果在 2018 年有预订,第一个 bool 查询将为真(因为开始日期将 > 2017-02-10),因此不会退还公寓,如果我是正确的。
我会做类似的事情:
:query => {
:nested: => {
:path: => "reservations",
:query => {
:bool => {
:must_not => [
{
:range => {:"reservations.start_date" => {:gte => "2017-02-10", :lte => "2017-02-12"}}
},
{
:range => {:"reservations.end_date" => {:gte => "2017-02-10", :lte => "2017-02-12"}}
}
]
}
}
}
}
这意味着您想要的范围内没有开始日期,您想要的范围内没有结束日期。
这是我提出的查询,应该考虑所有条件,即:
- 要么没有预订(1st top-level
bool/should
)
- 或至少有一项预订且预订开始和结束日期与请求日期不重叠。
在这里,我们要求在 2017-02-10
和 2017-02-12
之间提供免费公寓
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"nested": {
"path": "reservations",
"query": {
"bool": {
"must_not": {
"exists": {
"field": "reservations.start_date"
}
}
}
}
}
},
{
"bool": {
"must": [
{
"nested": {
"path": "reservations",
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"reservations.start_date": {
"gt": "2017-02-10"
}
}
},
{
"range": {
"reservations.end_date": {
"lt": "2017-02-10"
}
}
}
]
}
}
}
},
{
"nested": {
"path": "reservations",
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"reservations.start_date": {
"gt": "2017-02-12"
}
}
},
{
"range": {
"reservations.end_date": {
"lt": "2017-02-12"
}
}
}
]
}
}
}
}
]
}
}
]
}
}
我们必须列出免费公寓和那些将在所需时间段内可用的公寓(start_date、end_date 变量)
所以它应该是一个或查询:free_aparments or available_aparments
免费公寓(那些在预订字段中没有任何值的公寓)应该很容易通过缺少过滤器来查询,但这是一个嵌套字段,我们必须处理。
如果我们在缺少过滤器的情况下执行查询,将返回所有文档。这很奇怪,但确实发生了。这里有解释的解决方案:https://gist.github.com/Erni/7484095 and here is the issue: https://github.com/elastic/elasticsearch/issues/3495 gist snnipet 适用于所有 elasticsearch 版本。
or 查询的另一部分是可用的公寓。
我已经解决了这部分执行非查询。 Return 我是那些没有预订的公寓,想了一个与那些有预订的公寓相匹配的范围列表,然后使用 must_not 过滤器
否定结果
elasticsearch_query = {
"query": {
"filtered": {
"filter": {
"bool": {
"should": [
{
"nested": {
"filter": {
"bool": {
"must_not" : [
{
"range": {
"start_date": {
"gte" : start_date,
"lt" :end_date
}
}
},
{
"range": {
"end_date": {
"gte" : end_date,
#"lte" :end_date
}
}
}
]
}
},
"path": "reservations"
}
},
{
#{ "missing" : { "field" : "reservations"} }
"not": {
"nested": {
"path": "reservations",
"filter": {
"match_all": {}
}
}
}
}
],
}
}
},
},
"sort" : {"id":"desc"}
}
你可以在this notebook
中查看我的解决方案
我创建了一个示例,填充了一个示例索引并使用此查询搜索所需的公寓
评论回答:
Prefix: 由于执行了嵌套过滤器设置路径将被查询,所以根本不需要前缀(至少在我测试的版本中)。是的,您可以在文档级别或另一个嵌套字段
添加字段名称 start_date
公寓匹配:是的,它与 91 个样本公寓匹配,但由于我使用默认 size
参数执行了 search
,因此仅返回 10 个(我没有指定它的值,它的默认值)。如果您需要获取所有这些,请使用 scroll search
(已修改笔记本以阐明这一点)
概览
我有预订的公寓。我的索引有 嵌套字段 的保留,日期字段为 start_date 和 end_date。
我正在使用耐嚼的 ruby gem - 但我认为此时这并不重要。只需要让我的查询正确。
目标
我想获取在给定日期没有预订或根本没有预订的所有可用公寓。
当前查询
很遗憾returns所有公寓:
:query => {
:bool => {
:must_not => [
{
:range => {:"reservations.start_date" => {:gte => "2017-02-10"}}
},
{
:range => {:"reservations.end_date" => {:lte => "2017-02-12"}}
}
]
}
}
索引设置
{
"apartments" : {
"aliases" : { },
"mappings" : {
"apartment" : {
"properties" : {
"city" : {
"type" : "string"
},
"coordinates" : {
"type" : "geo_point"
},
"email" : {
"type" : "string"
},
"reservations" : {
"type" : "nested",
"properties" : {
"end_date" : {
"type" : "date",
"format" : "yyyy-MM-dd"
},
"start_date" : {
"type" : "date",
"format" : "yyyy-MM-dd"
}
}
},
"street" : {
"type" : "string"
},
"zip" : {
"type" : "string"
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1487289727161",
"number_of_shards" : "5",
"number_of_replicas" : "1",
"uuid" : "-rM79OUvQ3qkkLJmQCsoCg",
"version" : {
"created" : "2040499"
}
}
},
"warmers" : { }
}
}
首先,我认为你必须使用nested query。
我不熟悉 chewy-gem 但查询看起来像这样:
:query => {
:nested: => {
:path: => "reservations",
:query => {
:bool => {
:must_not => [
{
:range => {:"reservations.start_date" => {:gte => "2017-02-10"}}
},
{
:range => {:"reservations.end_date" => {:lte => "2017-02-12"}}
}
]
}
}
}
}
但它也可能无法正常工作,因为如果在 2018 年有预订,第一个 bool 查询将为真(因为开始日期将 > 2017-02-10),因此不会退还公寓,如果我是正确的。
我会做类似的事情:
:query => {
:nested: => {
:path: => "reservations",
:query => {
:bool => {
:must_not => [
{
:range => {:"reservations.start_date" => {:gte => "2017-02-10", :lte => "2017-02-12"}}
},
{
:range => {:"reservations.end_date" => {:gte => "2017-02-10", :lte => "2017-02-12"}}
}
]
}
}
}
}
这意味着您想要的范围内没有开始日期,您想要的范围内没有结束日期。
这是我提出的查询,应该考虑所有条件,即:
- 要么没有预订(1st top-level
bool/should
) - 或至少有一项预订且预订开始和结束日期与请求日期不重叠。
在这里,我们要求在 2017-02-10
和 2017-02-12
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"nested": {
"path": "reservations",
"query": {
"bool": {
"must_not": {
"exists": {
"field": "reservations.start_date"
}
}
}
}
}
},
{
"bool": {
"must": [
{
"nested": {
"path": "reservations",
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"reservations.start_date": {
"gt": "2017-02-10"
}
}
},
{
"range": {
"reservations.end_date": {
"lt": "2017-02-10"
}
}
}
]
}
}
}
},
{
"nested": {
"path": "reservations",
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"reservations.start_date": {
"gt": "2017-02-12"
}
}
},
{
"range": {
"reservations.end_date": {
"lt": "2017-02-12"
}
}
}
]
}
}
}
}
]
}
}
]
}
}
我们必须列出免费公寓和那些将在所需时间段内可用的公寓(start_date、end_date 变量)
所以它应该是一个或查询:free_aparments or available_aparments
免费公寓(那些在预订字段中没有任何值的公寓)应该很容易通过缺少过滤器来查询,但这是一个嵌套字段,我们必须处理。
如果我们在缺少过滤器的情况下执行查询,将返回所有文档。这很奇怪,但确实发生了。这里有解释的解决方案:https://gist.github.com/Erni/7484095 and here is the issue: https://github.com/elastic/elasticsearch/issues/3495 gist snnipet 适用于所有 elasticsearch 版本。
or 查询的另一部分是可用的公寓。
我已经解决了这部分执行非查询。 Return 我是那些没有预订的公寓,想了一个与那些有预订的公寓相匹配的范围列表,然后使用 must_not 过滤器
elasticsearch_query = {
"query": {
"filtered": {
"filter": {
"bool": {
"should": [
{
"nested": {
"filter": {
"bool": {
"must_not" : [
{
"range": {
"start_date": {
"gte" : start_date,
"lt" :end_date
}
}
},
{
"range": {
"end_date": {
"gte" : end_date,
#"lte" :end_date
}
}
}
]
}
},
"path": "reservations"
}
},
{
#{ "missing" : { "field" : "reservations"} }
"not": {
"nested": {
"path": "reservations",
"filter": {
"match_all": {}
}
}
}
}
],
}
}
},
},
"sort" : {"id":"desc"}
}
你可以在this notebook
中查看我的解决方案
我创建了一个示例,填充了一个示例索引并使用此查询搜索所需的公寓
评论回答:
Prefix: 由于执行了嵌套过滤器设置路径将被查询,所以根本不需要前缀(至少在我测试的版本中)。是的,您可以在文档级别或另一个嵌套字段
添加字段名称 公寓匹配:是的,它与 91 个样本公寓匹配,但由于我使用默认
size
参数执行了search
,因此仅返回 10 个(我没有指定它的值,它的默认值)。如果您需要获取所有这些,请使用 scroll search
start_date
(已修改笔记本以阐明这一点)