1

概述

我有预订的公寓。我的索引将保留作为嵌套字段,其中包含 start_date 和 end_date 的日期字段。

我正在使用耐嚼的红宝石 - 但我认为这并不重要。只需要让我的查询正确。

目标

我想获取在给定日期没有预订或根本没有预订的所有可用公寓。

当前查询

不幸的是返回所有公寓:

: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" : { }
  }
}
4

3 回答 3

1

我们必须列出免费公寓和那些将在所需期间可用的公寓(start_date,end_date 变量)

所以它应该是一个或查询:free_aparments 或 available_aparments

免费公寓(那些在预订字段中没有任何值的)应该缺少过滤器很容易查询,但这是一个嵌套字段,我们必须处理。
如果我们使用缺少的过滤器执行查询,则将返回所有文档。这很奇怪,但它确实发生了。这里有解释的解决方案:https ://gist.github.com/Erni/7484095 ,这里是问题:https ://github.com/elastic/elasticsearch/issues/3495 gist snnipet 适用于所有弹性搜索版本。

或查询的另一部分是可用的公寓。
我已经解决了这部分执行非查询。将那些没有预订的公寓返回给我,考虑与那些有预订的公寓匹配的范围列表,然后使用 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"}
}

您可以在我创建的这个笔记本
和示例中查看我的解决方案,填充示例索引并使用此查询搜索所需的公寓

评论答案:

  1. 前缀:由于执行嵌套过滤器设置路径将被查询,因此根本不需要前缀(至少在我测试的版本中)。是的,您可以start_date在文档级别或另一个嵌套字段中添加字段名称

  2. 公寓匹配:是的,它与 91 个样本公寓匹配,但由于我search使用默认size参数做了一个,因此只返回 10 个(我没有指定它的值,它的默认值)。如果您需要获取所有这些,请使用滚动搜索


(笔记本已被修改以澄清这一点)

于 2017-02-25T08:23:59.380 回答
0

这是我提出的查询,它应该考虑所有条件,即:

  • 要么没有保留(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"
                          }
                        }
                      }
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    ]
  }
}
于 2017-02-21T13:21:18.467 回答
0

首先,我认为您必须使用嵌套查询

我不熟悉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"}}
          }
        ]
      }
    }
  }
}

这意味着在您想要的范围之间没有开始日期,在您想要的范围之间没有结束日期。

于 2017-02-17T08:21:09.280 回答