2013-03-08 11 views
20

Elasticsearch hat zwei ähnliche Merkmale „ähnlich“ Dokumente zu erhalten:Elasticsearch „könnte dir auch gefallen“ API vs. more_like_this Abfrage

Es ist die "More Like This API". Es gibt mir Dokumente, die einem gegebenen ähnlich sind. Ich kann es jedoch nicht in komplexeren Ausdrücken verwenden.

Es gibt auch die "more_like_this" query for use in the Search API Ich kann es in Bool oder Boost-Ausdrücke verwenden, aber ich kann es nicht geben, eine ID eines Dokuments. Ich muss den Parameter "like_text" angeben.

Ich habe Dokumente mit Tags und Inhalt. Einige Dokumente haben gute Tags und einige haben keine. Ich möchte eine "Ähnliche Dokumente" -Funktion, die jedes Mal funktioniert, aber Dokumente mit übereinstimmenden Tags höher als Dokumente mit übereinstimmendem Text rankt. Meine Idee war:

{ 
    "boosting" : { 
     "positive" : { 
      "more_like_this" : { 
       "fields" : ["tag"], 
       "id" : "23452", 
       "min_term_freq" : 1 
      } 
     }, 
     "negative" : { 
      "more_like_this" : { 
       "fields" : ["tag"], 
       "id" : "23452", 
      } 
     }, 
     "negative_boost" : 0.2 
    } 
} 

Offensichtlich ist dies nicht funktioniert, weil es keine "id" in "more_like_this" ist. Was sind die Alternativen?

Antwort

41

Zunächst eine kleine Einführung über die mehr wie diese Funktionalität und wie es funktioniert. Die Idee ist, dass Sie ein bestimmtes Dokument haben und Sie möchten einige ähnliche haben.

Um dies zu erreichen, müssen wir etwas Inhalt aus dem aktuellen Dokument extrahieren und es verwenden, um eine Abfrage zu erstellen, um ähnliche zu erhalten. Wir können Inhalt aus den gespeicherten lucene-Feldern (oder dem Feld elasticsearch _source, das tatsächlich ein gespeichertes Feld in Lucene ist) extrahieren und irgendwie neu analysieren oder die in den Termvektoren gespeicherten Informationen verwenden (wenn sie während der Indizierung aktiviert sind), um eine Liste von Termen zu erhalten die wir verwenden können, um abzufragen, ohne den Text erneut analysieren zu müssen. Ich bin mir nicht sicher, ob elasticsearch diesen letzteren Ansatz versucht, wenn die Wortvektoren verfügbar sind.

Die more like this query können Sie einen Text bereitstellen, unabhängig davon, wo Sie es erhalten haben. Dieser Text wird verwendet, um die ausgewählten Felder abzufragen und ähnliche Dokumente zu erhalten. Der Text wird nicht vollständig verwendet, sondern erneut analysiert, und nur ein Maximum von max_query_terms (Standard 25) wird beibehalten, wobei die Bedingungen mindestens min_term_freq (minimale Termhäufigkeit, Standard 2) und Dokumenthäufigkeit zwischen min_doc_freq und max_doc_freq. Es gibt auch mehr Parameter, die die generierte Abfrage beeinflussen können.

Die more like this api geht noch einen Schritt weiter und erlaubt es, die ID eines Dokuments und wiederum eine Liste von Feldern bereitzustellen. Der Inhalt dieser Felder wird aus diesem bestimmten Dokument extrahiert und verwendet, um eine ähnliche Abfrage für die gleichen Felder zu erstellen. Das bedeutet, dass die mehr wie diese Abfrage erzeugte Eigenschaft den Text der Eigenschaft haben wird, der den zuvor extrahierten Text enthält, und wird für die gleichen Felder ausgeführt. Wie Sie sehen können, mehr wie diese API führt eine mehr wie diese Abfrage unter der Haube.

Nehmen wir an, je mehr diese Abfrage bietet Ihnen mehr Flexibilität, da Sie es mit anderen Abfragen kombinieren können, und Sie können den Text aus welcher Quelle auch immer Sie möchten. Auf der anderen Seite, mehr wie diese API zeigt die gemeinsame Funktionalität mehr Arbeit für Sie, aber mit einigen Einschränkungen.

In Ihrem Fall würde ich ein paar verschiedene mehr wie diese Abfragen zusammen kombinieren, so dass Sie die leistungsstarke elasticsearch Query DSL nutzen können, Anfragen anders auffrischen und so weiter. Der Nachteil ist, dass Sie den Text selbst bereitstellen müssen, da Sie die ID des Dokuments nicht angeben können, aus der es extrahiert werden soll.

Es gibt verschiedene Möglichkeiten, um das zu erreichen, was Sie wollen.Ich würde ein bool query verwenden, um die zwei mehr wie diese Abfragen in einer should-Klausel zu kombinieren und ihnen ein anderes Gewicht zu geben. Ich würde auch die more like this field query stattdessen verwenden, da Sie ein einzelnes Feld auf einmal abfragen möchten.

Auf diese Weise muss mindestens eine der should-Klauseln übereinstimmen, und eine Übereinstimmung der Tags ist wichtiger als eine Übereinstimmung des Inhalts.

+0

Danke für die Antwort. Die einzige Alternative zu dem nicht vorhandenen ''id' 'JSON-Namen besteht darin, den vollständigen Text zu erhalten und ihn in' "like_text" 'einzufügen. Es gibt keine Möglichkeit, den Rundgang des gesamten Textes zu vermeiden. Es gibt auch keine Möglichkeit, es zu reduzieren. Z.B. es gibt keine Möglichkeit, auf den Begriff Vektor eines Dokuments zuzugreifen und nur die 25 "Top-Begriffe" zu erhalten, so dass ich sie direkt in den "Like_Text" platzieren kann und die gleichen Ergebnisse bekomme wie mit dem Volltext. Bitte bestätigen. Ich habe darüber nachgedacht, ein elasticsearch plugin zu schreiben, das mir top n Begriffe für ein Dokument geben würde. Glaubst du, das würde funktionieren? –

+0

Soweit ich weiß, gibt es keine Out-of-the-Box-Art zu erreichen, was Sie wollen. Sie könnten wahrscheinlich ein Plugin schreiben, das eine neue Art von mehr wie diese Abfrage aufdeckt, die die ID eines Dokuments als Eingabe akzeptiert und den Text daraus abruft, eventuell sogar mit Termvektoren, wenn diese verfügbar sind. – javanna

8

Dies ist möglich, jetzt mit der neuen wie Syntax:

{ 
    "more_like_this" : { 
     "fields" : ["title", "description"], 
     "like" : [ 
     { 
      "_index" : "imdb", 
      "_type" : "movies", 
      "_id" : "1" 
     }, 
     { 
      "_index" : "imdb", 
      "_type" : "movies", 
      "_id" : "2" 
     }], 
     "min_term_freq" : 1, 
     "max_query_terms" : 12 
    } 
} 

Siehe hier: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html

+1

In den letzten ElasticSearch-Versionen wurde das Schlüsselwort 'docs' zugunsten von' like' veraltet. – cosimo

+0

@cosimo Aktualisiert die Antwort, danke – Datageek