2014-01-22 6 views
5

Ich möchte eine Anwendung erstellen, bei der eine Übereinstimmung erfordert, dass jedes Token im Dokument mindestens einmal in der Abfrage enthalten ist !!!Elasticsearch - Überprüfen, ob das Dokument in der Abfrage mit Synonymen enthalten ist

Bitte beachten Sie, dass es umgekehrt ist als die Standard Erwartung. Dokumente sind jetzt ziemlich klein, während Abfragen sehr lang sein können. Beispiel:

Dokument:

"elastic super cool". 

Eine gültige Abfrage Spiel

wäre
"I like elastic things since elasticsearch is super cool" 

ich es geschafft, die Anzahl der gefundenen Token von Elasticsearch zu bekommen (siehe auch https://groups.google.com/forum/?fromgroups=#!topic/elasticsearch/ttJTE52hXf8). Also im obigen Beispiel 3 Treffer (= Länge des Dokuments) würde bedeuten, dass die Abfrage übereinstimmt.

Aber wie kann ich das mit Synonymen kombinieren ???

Angenommen, ein Synonym für "cool" wäre "nett", "groß" und "gut". Durch Verwendung eines Synonym-Token-Filters konnte ich die Synonome zu jeder Position im Dokument hinzufügen.

Daher werden die folgenden vier Dokumente jeweils 3 Token oben für die Abfrage entspricht:

"elastic super nice" 

"elastic nice cool" 

"nice good great" 

"good great cool" 

Aber nur das erste Spiel ist ein gültiges Spiel!

Wie kann ich vermeiden, dass jede Synonymübereinstimmung als eine Übereinstimmung zählt, obwohl sie das gleiche Token im Dokument darstellen?

Irgendwelche Ideen, wie man dieses Problem anpackt?

ich gelesen, dass Perkolatoren dieses Problem beheben könnte, aber ich bin immer noch nicht sicher, ob perculators mit Synonymen, wie ich es möchte arbeiten würde ...

Ideen?

+0

Konnten Sie dieses Problem lösen? Haben Sie Percolator mit Synonymfilter probiert? – vaidik

Antwort

2

Ich nehme an, Sie erweitern die Synonyme. Sie können Skripts verwenden, um die übereinstimmenden Positionen zu zählen.

Elasticsearch Google Group with a solution by Vineeth Mohan

I sein Skript als nativer Skript angepasst ist, die eine Zahl zwischen 0 und 1 für das Verhältnis von passenden Positionen auf dem Feld zurück. Ich zwickte es ein wenig nur eine Position

Sie pro Abfrage ein Feld müssen übereinstimmen, die die Anzahl der Positionen enthält, beispielsweise durch token_count verwendet, die tatsächlich zählt die Anzahl der Positionen

@Override 
public Object run() 
{ 
    IndexField indexField = this.indexLookup().get(field); 
    Long numberOfPositions = ((ScriptDocValues.Longs) doc().get(positionsField)).getValue(); 

    ArrayList<Integer> positions = new ArrayList<Integer>(); 
    for (String term : terms) 
    { 
     Iterator<TermPosition> termPos = indexField.get(term, IndexLookup.FLAG_POSITIONS | IndexLookup.FLAG_CACHE) 
       .iterator(); 
     while (termPos.hasNext()) 
     { 
      int position = termPos.next().position; 
      if (positions.contains(position)) 
      { 
       continue; 
      } 
      positions.add(position); 
      // if the term matches multiple positions, only a new position should count 
      break; 
     } 
    } 

    return positions.size() * 1.0/numberOfPositions; 
} 

Sie können als Einsatz es in Ihrer Abfrage als ein function_score-Skript.

Sie können dann "min_score" auf 1 setzen und erhalten nur Dokumente, die alle Positionen in dem angegebenen Feld übereinstimmen.

Ich hoffe, dass diese Lösung ist, was Sie brauchen.

+0

Dies scheint ein häufiger Anwendungsfall zu sein. Gibt es einen besseren (out of the box) Weg, um dies jetzt zu handhaben, oder müssen wir nur mit der nativen Skriptlösung gehen? –

Verwandte Themen