如何在弹性搜索(aws)中存储日期范围数据并搜索范围?

时间:2016-06-15 00:43:24

标签: elasticsearch amazon-elasticsearch nosql

我正在尝试在elasticsearch中存储酒店房间的可用性。然后我需要 搜索房间从日期到另一个日期可用。我想出来了 有两种存储数据可用性的方法,它们如下:

此处可用性字典存储每个日期键的所有日期和值为true,表示其可用 那一天与否。

{
  "_id": "khg2uo47tyhgjwebu7624787",
  "room_type": "garden view",
  "hotel_name": "Cool hotel",
  "hotel_id": "jytu64r982u0299023",
  "room_metadata1": 233,
  "room_color": "black",
  "availability": {
    "2016-07-01": true,
    "2016-07-02": true,
    "2016-07-03": false,
    "2016-07-04": true,
    "2016-07-05": true,
    "2016-07-06": null,
    "2016-07-07": true,
    "2016-07-08": true,
    ----
    ----
    for 365 days 
  }

}

此处可用性数组仅存储空间可用时的那些日期

{
  "_id": "khg2uo47tyhgjwebu7624787",
  "room_type": "garden view",
  "hotel_name": "Cool hotel",
  "hotel_id": "jytu64r982u0299023",
  "room_metadata1": 535,
  "room_color": "black",
  "availability": ["2016-07-01", "2016-07-02", "2016-07-04", "2016-07-05", "2016-07-07", "2016-07-08"] ---for 365 days
  }
}

我想搜索所有房间,这些房间可从from_dateto_date,并且应该查看availability字典或数组。我的日期范围最长可达365天< / p>

如何存储这些可用性数据,以便我可以轻松执行上述搜索? 我找不到任何方法来搜索日期范围,所以有什么建议吗?

请注意,物品 在availability中可能无法保持排序。我可能有超过1亿条记录可供搜索。

2 个答案:

答案 0 :(得分:3)

对此进行建模的一种方法是使用父/子文档。房间文件将是父文件,可用文件将是他们的子文件。对于每个房间,每个房间可用的日期将有一个可用性文档。然后,在查询时,我们可以查询在搜索的间隔中每个日期都有一个可用性子文档的父房间(甚至是不相交的)。

请注意,您需要确保在预订房间后立即删除每个预订日期的相应子文档。

让我们试一试。首先创建索引:

PUT /rooms
{
  "mappings": {
    "room": {
      "properties": {
        "room_num": {
          "type": "integer"
        }
      }
    },
    "availability": {
      "_parent": {
        "type": "room"
      },
      "properties": {
        "date": {
          "type": "date",
          "format": "date"
        },
        "available": {
          "type": "boolean"
        }
      }
    }
  }
}

然后添加一些数据

POST /rooms/_bulk
{"_index": { "_type": "room", "_id": 233}}
{"room_num": 233}
{"_index": { "_type": "availability", "_id": "20160701", "_parent": 233}}
{"date": "2016-07-01"}
{"_index": { "_type": "availability", "_id": "20160702", "_parent": 233}}
{"date": "2016-07-02"}
{"_index": { "_type": "availability", "_id": "20160704", "_parent": 233}}
{"date": "2016-07-04"}
{"_index": { "_type": "availability", "_id": "20160705", "_parent": 233}}
{"date": "2016-07-05"}
{"_index": { "_type": "availability", "_id": "20160707", "_parent": 233}}
{"date": "2016-07-07"}
{"_index": { "_type": "availability", "_id": "20160708", "_parent": 233}}
{"date": "2016-07-08"}

最后,我们可以开始查询了。首先,假设我们想找到2016-07-01上可用的房间:

POST /rooms/room/_search
{
  "query": {
    "has_child": {
      "type": "availability",
      "query": {
        "term": {
          "date": "2016-07-01"
        }
      }
    }
  }
}
=> result: room 233

然后,让我们尝试搜索从2016-07-012016-07-03

的可用空间
POST /rooms/room/_search
{
  "query": {
    "bool": {
      "minimum_should_match": 3,
      "should": [
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-01"
              }
            }
          }
        },
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-02"
              }
            }
          }
        },
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-03"
              }
            }
          }
        }
      ]
    }
  }
}
=> Result: No rooms

但是,搜索从2016-07-012016-07-02的可用空间确实会产生233室

POST /rooms/room/_search
{
  "query": {
    "bool": {
      "minimum_should_match": 2,
      "should": [
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-01"
              }
            }
          }
        },
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-02"
              }
            }
          }
        }
      ]
    }
  }
}
=> Result: Room 233

我们还可以搜索不相交的时间间隔,例如从2016-07-012016-07-02 +从2016-07-042016-07-05

POST /rooms/room/_search
{
  "query": {
    "bool": {
      "minimum_should_match": 4,
      "should": [
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-01"
              }
            }
          }
        },
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-02"
              }
            }
          }
        },
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-04"
              }
            }
          }
        },
        {
          "has_child": {
            "type": "availability",
            "query": {
              "term": {
                "date": "2016-07-05"
              }
            }
          }
        }
      ]
    }
  }
}
=> Result: Room 233

依此类推......关键点是每个日期都需要添加一个has_child查询来检查可用性,并将minimum_should_match设置为您要检查的日期数。

<强>更新

另一种选择是使用script filter,但有1亿份文件,我不确定它是否可以很好地扩展。

在这种情况下,您可以保留原始设计(最好是第二个,因为第一个,您将在映射中创建太多不必要的字段),查询将如下所示:

POST /rooms/room/_search
{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "inline": "def dates = doc.availability.sort(false); from = Date.parse('yyyy-MM-dd', from); to = Date.parse('yyyy-MM-dd', to); def days = to - from; def fromIndex = doc.availability.values.indexOf(from.time); def toIndex = doc.availability.values.indexOf(to.time); return days == (toIndex - fromIndex)",
            "params": {
              "from": "2016-07-01",
              "to": "2016-07-04"
            }
          }
        }
      }
    }
  }
}

答案 1 :(得分:0)

我是新人,只是学习ES。这个设置/映射的缺点是什么?

ciao..remco