ElasticSearch - 日期范围条件应与日期范围数组中的EXACTLY一个项目匹配 [英] ElasticSearch - date range condition should match EXACTLY one item from date range array

查看:272
本文介绍了ElasticSearch - 日期范围条件应与日期范围数组中的EXACTLY一个项目匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我计划在弹性搜索中储存百万个空气净化型公寓。
其中 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:{
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
}
}
]
}
}
}
}
]
}
pre>

I am planning to store million of airbnb type apartments availabilty in elasticsearch . Where availabilty is an array that contains nested objects (availability type is nested). 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 one availability 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 one availability 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆