elasticsearch - ElasticSearch-日期范围条件应与日期范围数组中的一项完全匹配

标签 elasticsearch lucene amazon-elasticsearch nosql

我计划在Elasticsearch中存储数百万套Airbnb型公寓。
其中availabilty是一个包含nested对象的数组(availability类型为nested)。
每个对象都有日期范围,在该范围内可以使用该公寓。

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

我想搜索在特定日期范围内可用的公寓(例如2016-08-20 to 2016-12-12)。然后
范围应在各种公寓的可用日期范围之内。

所以我想写一个查询,就像:
{
  "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"} 
            }
        }
     ]
    }
  }
}

上面的查询将返回我两个公寓(具有与条件匹配的多个availability对象),
并且这是不正确的,它应该只返回带有_id: hgk87783iii86937jh的文档,因为确实有一个符合条件的availability对象与{"start": "2016-07-21", "end": "2016-12-19"}匹配。因此,为了获得正确的结果,条件应该是-公寓文档中应该有一个availability对象
应该符合条件的。因此,如何强制上述查询中完全匹配一个匹配项?第二个问题-我的查询是否正确?

最佳答案

使用nested query应该可以实现以上目标。
使用inner-hits获取匹配的availability-block
下面是实现此目的的示例:

创建索引

put testindex
{
    "mappings": {
        "data" : {
            "properties": {
                "availability" : {
                    "type": "nested"
                }
            }
        }
    }
}

索引数据:
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"
}

查询:
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": {}
               }
            }
         ]
      }
   }
}

结果:
"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 - ElasticSearch-日期范围条件应与日期范围数组中的一项完全匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37866833/

相关文章:

elasticsearch - 定制分析器,用例:邮政编码[ElasticSearch]

elasticsearch - 如何在 java api 的 should/must 方法中添加 bool 查询?

lucene - 根据语言更改字段的 Lucene 分析器

java - NoClassDefFoundError 创建 RestHighLevelClient bean 时出错

elasticsearch - 在Elasticsearch的多(全局)索引搜索中,如何在特定索引的特定字段上应用条件?

amazon-web-services - Elasticsearch 6.3(AWS)快照还原进度错误: “/_recovery is not allowed”

amazon-web-services - AWS Elasticsearch & VPC - 从我的固定 IP 配置网络访问

amazon-web-services - 是否可以将数据从 Redshift 传输到 Elasticsearch?

java - Solr 4.0 保留对已删除文件的引用

java - 为什么 BatchInserterIndex 多个字段的精确查询返回所有节点?