2016-06-16 15 views
0

Ich plane, Millionen von Airbnb Typ Wohnungen in elasticsearch verfügbar zu speichern. Wobei availabilty ein Array ist, das nested Objekte enthält (availability Typ ist nested). Und jedes dieser Objekte hat einen Datumsbereich, in dem diese Wohnung verfügbar ist.ElasticSearch - Datumsbereich Bedingung sollte genau einen Artikel aus dem Datumsbereich Array

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

Ich möchte Wohnungen suchen die für einen bestimmten Zeitraum zur Verfügung stehen (zB 2016-08-20 to 2016-12-12). Und diese Reichweite sollte in einen der Verfügbarkeitszeiträume verschiedener Wohnungen fallen.

Deshalb möchte ich eine Abfrage schreiben, so etwas wie:

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

Und obige Abfrage wird mir beide Wohnungen zurückkehren (mit mehreren availability Objekte passend zur Bedingung), und das ist falsch, es sollte nur Rückkehr Dokument mit _id: hgk87783iii86937jh wie es genau ein availability Objekt entspricht den creiteria und das ist {"start": "2016-07-21", "end": "2016-12-19"}. Also, um ein korrektes Ergebnis zu haben, sollte die Bedingung sein - es sollte GENAU ein availability Objekt in der Wohnung doc sein, das sollte der Bedingung entsprechen. Wie also erzwingen, dass es genau eine Übereinstimmung in der obigen Abfrage geben sollte? Zweite Frage - ist meine Anfrage überhaupt richtig?

+0

stellen Sie sicher, die Zuordnung für 'availability' vom Typ [verschachtelte] (https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-mapping .html) und dann sollte es möglich sein, [verschachtelte Abfrage] zu verwenden (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html) – keety

+0

@keety Ja das werde ich haben wie ich auch in der Post erwähnt habe. Aber meine Frage ist, wie bekomme ich nur die Dokumente, bei denen GENAU ein Verfügbarkeitsobjekt mit der Bedingung übereinstimmt? – JVK

+0

könnten Sie ein Beispiel geben, dessen "verfügbares Objekt" die Bedingung für den oben genannten Fall erfüllen würde? – keety

Antwort

1

Mit nested query sollten Sie das oben genannte erreichen können. Verwenden Sie inner-hits, um die übereinstimmende availability-block zu erhalten. Unten ist ein Beispiel, dies umzusetzen:

Index erstellen

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

Index Daten:

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

Abfrage:

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

Ergebnisse:

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

Vielen Dank @keety für Ihre Lösung. Meine Frage - mit "inner_hits" kann mehr als ein Hits-Objekt zurückgegeben werden, das den Suchkriterien entspricht. oder es wird immer ein Objekt zurückgeben? Wenn es mehr als eins zurückgibt, dann wird mir das nicht weiterhelfen ... oder? – JVK

+0

Ich bin upvoting Ihre Lösung obwohl :) – JVK

+0

schätzen die upvote, ich bin nur neugierig, ist es sogar möglich für ein Dokument, mehr als ein verfügbares Objekt zu haben, das die criteria erfüllt?Können Sie ein Beispiel angeben, bei dem die obige Abfrage mehr als ein Objekt zurückgeben würde? – keety