2016-08-15 1 views
1

ich verwende Elasticsearch 2.3Elasticsearch 2.x-Abfrage für Tag und sortieren Ergebnisse nach Tag weigth

Ich habe einen Index der Bücher. Jedes Buch hat ein Tag und jedes Tag hat ein Gewicht. Ich möchte alle Bücher erhalten, die das gewünschte Tag haben, sortiert nach Tag Gewicht.

zum Beispiel:

PUT book/book/0 
{ 
    "name": "book 0", 
    "tags": [ 
     {"t": "comedy", "w": 30}, 
     {"t": "drama","w": 20}, 
    ] 
} 

PUT book/book/1 
{ 
    "name": "book 1", 
    "tags": [ 
     {"t": "comedy", "w": 10}, 
     {"t": "drama","w": 5}, 
     {"t": "other","w": 50}, 
    ] 
} 

PUT book/book/2 
    { 
     "name": "book 2", 
     "tags": [ 
      {"t": "comedy", "w": 5}, 
      {"t": "drama","w": 30}, 
     ] 
    } 

PUT book/book/3 
    { 
     "name": "book 3", 
     "tags": [ 
      {"t": "comedy", "w": 5}, 
      {"t": "other","w": 30}, 
     ] 
    } 

Ich möchte für alle Bücher suchen, die Tags Komödie und Drama hat. das Ergebnis Reihenfolge ist:

  1. Buch 0 (20 + 30)
  2. Buch 2 (30 + 5)
  3. Buch 1 (10 + 5)

UPDATE: i möchte um nur Bücher zurückzugeben, die mit beiden Tags übereinstimmen (und nur nach angeforderten Tags sortieren). Wenn ich nach "Drama" und "Komödie" suche, werden nur Bücher zurückgegeben, die beide Tags haben (in diesem Fall Buch 0, Buch 1, Buch 2), sortiert nach den angeforderten Tag-Gewichten.

wie kann ich diese bekommen? ein beliebiges Beispiel für eine Abfrage?

Antwort

3

Ibrahim's answer korrekt ist, wenn Sie immer alle Gewichte summieren wollen, auch für Tags, die Ihrer Anfrage nicht entsprechen. Wenn Sie nur die Gewichtungen von Tags berücksichtigen möchten, nach denen Sie suchen, müssen Sie tags als nested Objekt indizieren. Dies liegt daran, sonst alle t s und w s sind in Listen abgeflacht, die Verbände in dem Prozess zu verlieren (beschrieben here).

Dann können Sie eine function_score Abfrage in eine nested Abfrage verpackt, um nur die Gewichte der übereinstimmenden Tags zusammenzufassen. Sie müssen scripting aktivieren. Hier

ein Beispiel:

GET /book/_search 
{ 
    "query": { 
    "nested": { 
     "path": "tags", 
     "query": { 
     "function_score": { 
      "query": { 
      "bool": { 
       "filter": [ 
       { 
        "terms": { 
        "tags.t": [ 
         "comedy", 
         "drama" 
        ] 
        } 
       } 
       ] 
      } 
      }, 
      "functions": [ 
      { 
       "script_score": { 
       "script": "return doc['tags.w'].value" 
       } 
      } 
      ], 
      "boost_mode": "replace" 
     } 
     }, 
     "score_mode": "sum" 
    } 
    } 
} 


=== EDIT folgende @Eyal Ch Kommentar ===

Wenn nur Bücher BEIDE Tags (Komödie und Drama im Beispiel) passend werden zurückgegeben, es wird etwas komplizierter, da jeder Suchbegriff eine eigene nested Abfrage benötigt.

Hier ist ein Beispiel:

GET /book/_search 
{ 
    "query": { 
    "bool": { 
     "must": 
     [ 
     { 
      "nested": { 
      "path": "tags", 
      "query": { 
       "function_score": { 
       "query": { 
        "term": { 
        "tags.t": { 
         "value": "comedy" 
        } 
        } 
       }, 
       "functions": [ 
        { 
        "script_score": { 
         "script": "return doc['tags.w'].value" 
        } 
        } 
       ], 
       "boost_mode": "replace" 
       } 
      } 
      } 
     }, 
     { 
      "nested": { 
      "path": "tags", 
      "query": { 
       "function_score": { 
       "query": { 
        "term": { 
        "tags.t": { 
         "value": "drama" 
        } 
        } 
       }, 
       "functions": [ 
        { 
        "script_score": { 
         "script": "return doc['tags.w'].value" 
        } 
        } 
       ], 
       "boost_mode": "replace" 
       } 
      } 
      } 
     } 
    ] 
    } 
    } 
} 
+0

danke @Christoph Wurm. das einzige Problem, das ich jetzt habe, ist, dass dies alle Bücher, die Komödie oder Drama in Tags zurückgeben wird. aber ich brauche alle Bücher, die Komödie und Drama in Tags. kannst du helfen? –

+0

@EyalCh Ja, ich habe es in die Antwort eingefügt. –

+0

danke das funktioniert !. nur um zu verstehen: in ihrer aktualisierten antwort sehe ich nicht "score_mode": "summe". wie es die Punktzahl summerize? ist es standardmäßig?wenn ich es in einer anderen Punktzahl (wie AVG?) Vielen Dank. –

1

Versuchen Sie folgendes:

POST book/book/_search 
{ 
    "query": { 
     "match": { 
      "tags.t": "comedy drama" 
     } 
    }, 
    "sort": [ 
     { 
      "tags.w": { 
      "order": "desc", 
      "mode": "sum" 
      } 
     } 
    ] 
} 
+0

dies wird von allen Tags sortieren, indem Sie 'w'. Ich möchte es nur nach der Reihenfolge der angeforderten Tags sortieren (w der Komödie + w des Dramas) –

Verwandte Themen