web-dev-qa-db-de.com

ElasticSearch - Steigerung der Relevanz basierend auf dem Feldwert

Sie müssen in ElasticSearch einen Weg finden, um die Relevanz eines Dokuments basierend auf einem bestimmten Wert eines Felds zu steigern. Insbesondere gibt es in allen meinen Dokumenten ein spezielles Feld. Je höher der Feldwert, desto relevanter sollte das Dokument sein, das es enthält, unabhängig von der Suche.

Betrachten Sie die folgende Dokumentstruktur:

{
    "_all" : {"enabled" : "true"},
    "properties" : {
        "_id":            {"type" : "string",  "store" : "yes", "index" : "not_analyzed"},
        "first_name":     {"type" : "string",  "store" : "yes", "index" : "yes"},
        "last_name":      {"type" : "string",  "store" : "yes", "index" : "yes"},
        "boosting_field": {"type" : "integer", "store" : "yes", "index" : "yes"}
        }
}

Ich möchte, dass Dokumente mit einem höheren boosting_field-Wert von Natur aus relevanter sind als solche mit einem niedrigeren boosting_field-Wert. Dies ist nur ein Ausgangspunkt - die Übereinstimmung zwischen der Abfrage und den anderen Feldern wird auch bei der Bestimmung des endgültigen Relevanzfaktors jedes Dokuments in der Suche berücksichtigt. Aber alles andere ist gleich, je höher das Verstärkungsfeld, desto relevanter das Dokument.

Hat jemand eine Idee, wie das geht?

Danke vielmals!

62
Clay Wardell

Sie können entweder zur Indexzeit oder zur Abfragezeit einen Boost durchführen. Normalerweise bevorzuge ich das Boosten der Abfragezeit, obwohl dadurch die Abfragen etwas langsamer werden. Andernfalls muss ich jedes Mal neu indizieren, wenn ich meine Boosting-Faktoren ändern möchte, die normalerweise eine Feinabstimmung erfordern und ziemlich flexibel sein müssen.

Es gibt verschiedene Möglichkeiten, die Abfragezeit mithilfe der elasticsearch-Abfrage DSL zu erhöhen:

Die ersten drei Abfragen sind nützlich, wenn Sie den Dokumenten, die mit bestimmten Abfragen oder Filtern übereinstimmen, einen bestimmten Schub verleihen möchten. Zum Beispiel, wenn Sie nur die Dokumente verbessern möchten, die im letzten Monat veröffentlicht wurden. Sie könnten diesen Ansatz für Ihr boosting_field verwenden, aber Sie müssten einige boosting_field-Intervalle manuell definieren und ihnen einen anderen Schub geben, was nicht so toll ist.

Die beste Lösung wäre die Verwendung einer Custom Score Query , mit der Sie eine Abfrage erstellen und ihre Bewertung mithilfe eines Skripts anpassen können. Es ist ziemlich leistungsfähig, mit dem Skript können Sie die Partitur selbst direkt ändern. Zuallererst würde ich die boosting_field-Werte auf einen Wert von 0 bis 1 skalieren, damit Ihre endgültige Punktzahl nicht zu einer großen Zahl wird. Um dies zu tun, müssen Sie vorhersagen, welche Werte mehr oder weniger die minimalen und maximalen Werte sein können, die das Feld enthalten kann. Nehmen wir zum Beispiel Minimum 0 und Maximum 100000 an. Wenn Sie den Wert von boosting_field auf eine Zahl zwischen 0 und 1 skalieren, können Sie das Ergebnis folgendermaßen zur tatsächlichen Punktzahl hinzufügen:

{
    "query" : {
        "custom_score" : {
            "query" : {
                "match_all" : {}
            },
            "script" : "_score + (1 * doc.boosting_field.doubleValue / 100000)"
        }
    }
}

Sie können auch erwägen, das Feld boosting_field als Boost-Faktor zu verwenden (_score * eher, als _score +), aber dann müssten Sie es auf ein Intervall mit dem Mindestwert 1 skalieren (fügen Sie einfach ein +1 hinzu).

Sie können das Ergebnis sogar optimieren, um die Bedeutung der Änderung zu ändern, indem Sie dem Wert, den Sie zur Beeinflussung der Punktzahl verwenden, eine Gewichtung hinzufügen. Sie werden dies noch mehr brauchen, wenn Sie mehrere Boosting-Faktoren miteinander kombinieren müssen, um ihnen ein anderes Gewicht zu verleihen.

69
javanna

In einer neueren Version von Elasticsearch (Version 1.3+) möchten Sie "Funktions-Score-Abfragen" verwenden:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

Eine bewertete query_string-Suche sieht folgendermaßen aus:

{
 'query': {
        'function_score': {
            'query': { 'query_string': { 'query': 'my search terms' } },
            'functions': [{ 'field_value_factor': { 'field': 'my_boost' } }]
        }
    }
}

"my_boost" ist ein numerisches Feld in Ihrem Suchindex, das den Boost-Faktor für einzelne Dokumente enthält. Kann so aussehen:

{ "my_boost": { "type": "float", "index": "not_analyzed" } }
13

wenn Sie vermeiden möchten, das Boosten jedes Mal in der Abfrage durchzuführen, können Sie es Ihrem Mapping hinzufügen, indem Sie direkt "boost: factor" hinzufügen.

Ihr Mapping könnte dann so aussehen:

{
    "_all" : {"enabled" : "true"},
    "properties" : {
        "_id":            {"type" : "string",  "store" : "yes", "index" : "not_analyzed"},
        "first_name":     {"type" : "string",  "store" : "yes", "index" : "yes"},
        "last_name":      {"type" : "string",  "store" : "yes", "index" : "yes"},
        "boosting_field": {"type" : "integer", "store" : "yes", "index" : "yes", "boost" : 10.0,}
        }
}
3
HolgT