3

ホテルの空室状況をelasticsearchに保存しようとしています。そして、ある日付から別の日付まで利用可能な部屋を検索する必要があります。可用性のためにデータを保存する 2 つの方法を考え出しました。それらは次のとおりです。

ここで、空室状況ディクショナリはすべての日付を格納し、各日付キーの値は true または false であり、その日に利用可能かどうかを表します。

{
  "_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_dateまで利用可能であり、辞書または配列to_dateを調べる必要があります.availabilityそして、私の日付範囲は最大365日にわたる場合があります

上記の検索を簡単に実行できるように、これらの可用性データを保存する方法は? そして、日付の範囲を検索する方法が見つからなかったので、何か提案はありますか?

availabilityのアイテムはソートされていない場合がありますのでご注意ください。また、検索するレコードが 1 億件を超える場合もあります。

4

2 に答える 2

3

これをモデル化する 1 つの方法は、親/子ドキュメントを使用することです。ルーム ドキュメントは親ドキュメントになり、空き時間ドキュメントは子ドキュメントになります。部屋ごとに、部屋が利用可能な日付ごとに 1 つの空室状況ドキュメントがあります。次に、クエリ時に、検索間隔内の日付ごとに 1 つの空室状況の子ドキュメントを持つ親ルームをクエリできます (バラバラの場合でも)。

部屋が予約されるとすぐに、予約された日付ごとに対応する子ドキュメントを削除する必要があることに注意してください。

これを試してみましょう。最初にインデックスを作成します。

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-01では、 ~から空室のあるお部屋を探してみましょう。2016-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-01ただし、 ~から利用可能な部屋を検索すると、2016-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-01from to 2016-07-02+ from 2016-07-04toなど、互いに素な区間を検索することもできます。2016-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空室状況を確認する必要がある日付ごとに 1 つのクエリを追加し、確認minimum_should_matchする日付の数を設定することです。

アップデート

もう 1 つのオプションはscriptfilterを使用することですが、1 億のドキュメントがあるため、それほどうまくスケーリングできるかどうかはわかりません。

このシナリオでは、元の設計を維持できます (最初の設計ではマッピングに不要なフィールドが多すぎるため、2 番目の設計が望ましい)、クエリは次のようになります。

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"
            }
          }
        }
      }
    }
  }
}
于 2016-06-15T06:35:00.223 に答える