2016-12-12 2 views
0

Ich versuche, die Suche nach Endbenutzer mit Typ, wie sie gehen, die mehr wie SQL Server ist. konnte ich ES Abfrage für das angegebene SQL-Szenario implementieren:Wilcard Suche oder Teilabgleich in Elastic Suche

select * from table where name like '%pete%' and type != 'xyz and type!='abc' 

Aber die ES-Abfrage funktioniert nicht für diese SQL-Abfrage

select * from table where name like '%peter tom%' and type != 'xyz and type!='abc' 

In meinem Elasticsearch alongwith der Wildcard-Abfrage muss ich auch führen Sie einige boolean gefilterten Abfrage

{ 
"query": { 
"filtered": { 
"filter": { 
"bool": { 
"should": [ 
{ 
"query": { 
"wildcard": { 
"name": 
{ "value": "*pete*" } 
} 
} 
} 
], 
"must_not": [ 
{ 
"match": 
{ "type": "xyz" } 
}, { 
"match": 
{ "type": "abc" } 
} 
] 
} 
} 
} 
} 
} 

Die obige elastische Abfrage mit Wildcard-Suche funktioniert gut und wird mir alle Dokumente, die pete Spiele und sind nicht vom Typ xyz und abc .Aber wenn ich die Wildcard mit 2 seprate Worten versuchen ausführen seprated von Raum die gleiche Abfrage gibt mir dann, wie gezeigt leer below.For Beispiel

{ 
    "query": { 
    "filtered": { 
    "filter": { 
    "bool": { 
    "should": [ 
    { 
    "query": { 
    "wildcard": { 
    "name": 
    { "value": "*peter tom*" } 
    } 
    } 
    } 
    ], 
    "must_not": [ 
    { 
    "match": 
    { "type": "xyz" } 
    }, { 
    "match": 
    { "type": "abc" } 
    } 
    ] 
    } 
    } 
    } 
    } 
    } 

Meine Mapping folgt als:

{ 
    "properties": { 
    "name": { 
     "type": "string" 
    } 
    "type": { 
     "type": "string" 
    } 
    } 
} 

Welche Abfrage soll ich verwenden, um nach Worten Wildcard-Suche möglich zu machen seprated durch Leerzeichen

+0

Sie Problem ist, dass Sie verstehen nicht, wie ES Indizierung von Daten. Schauen Sie dazu https://www.elastic.co/guide/en/elasticsearch/guide/current/inverted-index.html. Schauen Sie auch auf ngGram https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html –

+0

Also Problem ist, dass, wenn Sie den Text "Hallo Welt" in ES indexieren wird es [werden "Hallo Welt"]. –

+0

Ich verstehe, wie Dokumente in ES gespeichert werden, aber was bietet ES, um Benutzern zu ermöglichen, sql wie Suche nach Wörtern getrennt durch Leerzeichen auszuführen, ist meine Frage – andy

Antwort

2

Die effizienteste Lösung besteht darin, eine ngram tokenizer zu verwenden, um Teile Ihres name Feldes zu tokenisieren.Zum Beispiel, wenn Sie einen Namen wie peter tomson haben, wird die ngram tokenizer tokenize und indizieren wie folgt aus:

  • pe
  • pet
  • pete
  • Peter
  • Peter t
  • Peter zu
  • Peter Tom
  • Peter Toms
  • Peter tomso
  • eter tomson
  • ter tomson
  • er tomson
  • r tomson
  • tomson
  • tomson
  • omson
  • mson
  • Sohn
  • auf

Also, wenn dies indiziert wurde, wird die Suche nach einem dieser Token Ihr Dokument mit peter thomson darin abrufen.

Lassen Sie uns den Index erstellen:

PUT likequery 
{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "my_ngram_analyzer": { 
      "tokenizer": "my_ngram_tokenizer" 
     } 
     }, 
     "tokenizer": { 
     "my_ngram_tokenizer": { 
      "type": "nGram", 
      "min_gram": "2", 
      "max_gram": "15" 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "typename": { 
     "properties": { 
     "name": { 
      "type": "string", 
      "fields": { 
      "search": { 
       "type": "string", 
       "analyzer": "my_ngram_analyzer" 
      } 
      } 
     }, 
     "type": { 
      "type": "string", 
      "index": "not_analyzed" 
     } 
     } 
    } 
    } 
} 

Sie werden dann wie folgt suchen können mit einem einfachen und sehr effizienten term Abfrage:

POST likequery/_search 
{ 
    "query": { 
    "bool": { 
     "should": [ 
     { 
      "term": { 
      "name.search": "peter tom" 
      } 
     } 
     ], 
     "must_not": [ 
     { 
      "match": { 
      "type": "xyz" 
      } 
     }, 
     { 
      "match": { 
      "type": "abc" 
      } 
     } 
     ] 
    } 
    } 
} 
+0

danke für Ihr Feedback, würden Sie wissen lassen, dass die Spezifika dieser 2 Attribute: "min_gram": "2", "max_gram": "15" .is 2 darstellt das Bigramm, was bedeutet in diesem Fall max_gram. Auch ist Ngram in Version 2.1 verfügbar? – andy

+0

'min_gram' ist die minimale Anzahl von Zeichen (nicht Wörter) und' max_gram' ist die maximale Anzahl an Zeichen. Dies bedeutet, dass dieser Tokenizer alle Zeichenketten der Länge 2 bis 15, die aus Ihren Namenswerten gemacht werden können, in Tokens umsetzt. – Val

+0

ok ich sehe, danke – andy

1

Nun ist meine Lösung nicht perfekt und ich bin mir nicht sicher über die Leistung. So sollten Sie es auf Ihr eigenes Risiko versuchen :)

Dies ist ES-5-Version

PUT likequery 
{ 
    "mappings": { 
    "typename": { 
     "properties": { 
     "name": { 
      "type": "string", 
      "fields": { 
      "raw": { 
       "type": "keyword" 
      } 
      } 
     }, 
     "type": { 
      "type": "string" 
     } 
     } 
    } 
    } 
} 

in ES 2.1 Änderung "type": "Schlüsselwort" zu "type": "string", "index": "not_analyzed"

PUT likequery/typename/1 
{ 
    "name": "peter tomson" 
} 

PUT likequery/typename/2 
{ 
    "name": "igor tkachenko" 
} 

PUT likequery/typename/3 
{ 
    "name": "taras shevchenko" 
} 

Query ist Fall sensetive

POST likequery/_search 
{ 
    "query": { 
    "regexp": { 
     "name.raw": ".*taras shev.*" 
    } 
    } 
} 

Antwort

{ 
    "took": 5, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 1, 
    "max_score": 1, 
    "hits": [ 
     { 
     "_index": "likequery", 
     "_type": "typename", 
     "_id": "3", 
     "_score": 1, 
     "fields": { 
      "raw": [ 
      "taras shevchenko" 
      ] 
     } 
     } 
    ] 
    } 
} 

PS. Noch einmal bin ich nicht sicher über die Leistung dieser Abfrage, da es Scan und nicht Index verwenden wird.

+0

danke geben Sie einen Versuch jetzt – andy

Verwandte Themen