2016-07-22 28 views
0

Ich habe viele Dokumente mit einer rate Eigenschaft, die ein Array mit Min/Max-Bereich der akzeptierten Preise ist.Elasticsearch: Wie Abfrage für Bereich basierend auf Array mit Max/Min-Werten

{ "rate": [250, 700] } 

Ich möchte nun Abfragen durchführen einen anderen Bereich, zum Beispiel die Bereitstellung:

{ 
    "bool": { 
    "must": [ 
     "range": { 
     "rate": { "from": 100, "to": 500 } 
     } 
    ] 
    } 
} 

Das feine und gibt immer Werte arbeitet, die innerhalb des Bereichs mindestens einer der Werte bereitgestellt, das ist das, was Ich will.

Für alle Ergebnisse ist die Bewertung jedoch gleich. Es spielt keine Rolle, ob der Wert dem des Dokuments entspricht oder ob er nur den Bereich für einige Zahlen erreicht. Wie unten dargestellt:

{ 
    "_id": "one", 
    "_score": 1", 
    "_source": { "rate": [250,750] } 
}, 
{ 
    "_id": "two", 
    "_score": 1", 
    "_source": { "rate": [200,350] } 
}, 
{ 
    "_id": "three", 
    "_score": 1", 
    "_source": { "rate": [500,750] } 
} 

Gibt es eine Möglichkeit, eine Bereichssuche bietet einen anderen Bereich wie diese zu verbessern?

Antwort

0

Sie fragen nach einer range, die implizit eine Ja oder Nein-Frage ist. Es ist eigentlich komisch, überhaupt gegen alles zu punkten, außer als Booster (wie in: Wenn es dann ist, dann steigern Sie die Punktzahl, aber wenn es nicht ist, dann ist das in Ordnung). Als solche range Abfragen tendieren am besten im Filterkontext zu verwenden.

"query": { 
    "bool": { 
    "filter": [ 
     { 
     "range": { 
      "rate": { "gte": 100, "lte": 500 } 
     } 
     } 
    ] 
    } 
} 

(Syntax geht davon aus ES 2.0)

Bist du das wirklich nicht helfen, aber es ist der bessere Weg, um die Anforderung zu tun, die Sie tun.

Was Sie fragen, möchten Sie basierend auf den Rohwert (en) im Dokument gewichten. Dies ist viel weniger gerade, weil der Wert ein Array mit Werten ist, die potenziell außerhalb der Grenzen sein können, und es ist kein nested Objekt, so dass es immer als ein Array behandelt wird (was bedeutet, dass Sie die ignorierten manuell erneut ausschließen müssen) Ergebnisse).

Vollständig benutzerdefinierte Scoring erfordert Skripte (nativ oder anders), und dies kann leicht mit einem Skript-Score erreicht werden.

Es spielt keine Rolle, ob der Wert dem des Dokuments entspricht oder ob er nur den Bereich für einige Zahlen erreicht.

Ich verstehe eigentlich nicht, was der erste Teil bedeutet: Wollen Sie, dass ein einzelnes Spiel weniger oder mehr "wiegt"? Ist der Abstand von den Rändern wichtig? Passt das nur zusammen?

werde ich den Fall übernehmen, dass mehr Spiele besser ist, und zwar unabhängig davon, wo sie in dem Bereich fallen:

{ 
    "query": { 
    "bool": { 
     "must": { 
     "function_score": { 
      "functions": [ 
      { 
       "script_score": { 
       "script": { 
        "inline": "doc['rate'].values.findAll { it >= gte && it <= lte }.size()", 
        "lang": "groovy", 
        "params": { 
        "gte": 100, 
        "lte": 500 
        } 
       } 
       } 
      } 
      ], 
      "boost_mode": "replace" 
     } 
     }, 
     "filter": [ 
     { 
      "range": { 
      "rate": { 
       "gte": 100, 
       "lte": 500 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

Sie sollten not be using inline Groovy scripts in production (Verwendung Datei-basierte Skripte statt), aber die oben arbeiten.

+0

Danke, @pickypg, ich hatte eigentlich vergessen, die Bereichsabfrage hinzuzufügen, als ich die Frage stellte (behoben). Leider habe ich keinen Zugriff auf Groovy, da ich den AWS ES-Service nutze. Würdest du an irgendeine andere Idee denken, die es zum Laufen bringen könnte? Ich könnte die Daten anders modellieren, wenn das hilft, aber ich fand, dass getrennte Werte wie 'rate_from' und' rate_to' noch komplizierter wurden.Die Idee ist, dass je mehr es einem Bereich innerhalb des Bereichs entspricht oder den höheren Wert bewertet (wenn 100500 zur Verfügung gestellt werden, würde eine 100,500 Eingabe 100% Übereinstimmung sein, während 400, 700 nicht so viel ist. – zanona