2016-03-24 2 views
0

Ich möchte Fuzzy-Match für E-Mail oder Telefon von Elasticsearch machen. Zum Beispiel:Wie zu Fuzzy Match E-Mail oder Telefon von Elasticsearch?

Spiel aller E-Mails enden mit @gmail.com

oder

Spiel all Telefon startwith 136.

Ich weiß, ich Platzhalter verwenden kann,

{ 
"query": { 
    "wildcard" : { 
     "email": "*gmail.com" 
    } 
    } 
} 

aber die Leistung ist sehr schlecht. Ich versuchte, regexp zu verwenden:

{"query": {"regexp": {"email": {"value": "*163\.com*"} } } } 

funktioniert aber nicht.

Gibt es einen besseren Weg, es zu machen?

curl -XGET localhost: 9200/user_data

{ 
    "user_data": { 
     "aliases": {}, 
     "mappings": { 
      "user_data": { 
       "properties": { 
        "address": { 
         "type": "string" 
        }, 
        "age": { 
         "type": "long" 
        }, 
        "comment": { 
         "type": "string" 
        }, 
        "created_on": { 
         "type": "date", 
         "format": "dateOptionalTime" 
        }, 
        "custom": { 
         "properties": { 
          "key": { 
           "type": "string" 
          }, 
          "value": { 
           "type": "string" 
          } 
         } 
        }, 
        "gender": { 
         "type": "string" 
        }, 
        "name": { 
         "type": "string" 
        }, 
        "qq": { 
         "type": "string" 
        }, 
        "tel": { 
         "type": "string" 
        }, 
        "updated_on": { 
         "type": "date", 
         "format": "dateOptionalTime" 
        }, 
       } 
      } 
     }, 
     "settings": { 
      "index": { 
       "creation_date": "1458832279465", 
       "uuid": "Fbmthc3lR0ya51zCnWidYg", 
       "number_of_replicas": "1", 
       "number_of_shards": "5", 
       "version": { 
        "created": "1070299" 
       } 
      } 
     }, 
     "warmers": {} 
    } 
} 

die Abbildung:

{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "index_phone_analyzer": { 
      "type": "custom", 
      "char_filter": [ "digit_only" ], 
      "tokenizer": "digit_edge_ngram_tokenizer", 
      "filter": [ "trim" ] 
     }, 
     "search_phone_analyzer": { 
      "type": "custom", 
      "char_filter": [ "digit_only" ], 
      "tokenizer": "keyword", 
      "filter": [ "trim" ] 
     }, 
     "index_email_analyzer": { 
      "type": "custom", 
      "tokenizer": "standard", 
      "filter": [ "lowercase", "name_ngram_filter", "trim" ] 
     }, 
     "search_email_analyzer": { 
      "type": "custom", 
      "tokenizer": "standard", 
      "filter": [ "lowercase", "trim" ] 
     } 
     }, 
     "char_filter": { 
     "digit_only": { 
      "type": "pattern_replace", 
      "pattern": "\\D+", 
      "replacement": "" 
     } 
     }, 
     "tokenizer": { 
     "digit_edge_ngram_tokenizer": { 
      "type": "edgeNGram", 
      "min_gram": "3", 
      "max_gram": "15", 
      "token_chars": [ "digit" ] 
     } 
     }, 
     "filter": { 
     "name_ngram_filter": { 
      "type": "ngram", 
      "min_gram": "3", 
      "max_gram": "20" 
     } 
     } 
    } 
    }, 
    "mappings" : { 
    "user_data" : { 
     "properties" : { 
     "name" : { 
      "type" : "string", 
      "analyzer" : "ik" 
     }, 
     "age" : { 
      "type" : "integer" 
     }, 
     "gender": { 
      "type" : "string" 
     }, 
     "qq" : { 
      "type" : "string" 
     }, 
     "email" : { 
      "type" : "string", 
      "analyzer": "index_email_analyzer", 
      "search_analyzer": "search_email_analyzer" 
     }, 
     "tel" : { 
      "type" : "string", 
      "analyzer": "index_phone_analyzer", 
      "search_analyzer": "search_phone_analyzer" 
     }, 
     "address" : { 
      "type": "string", 
      "analyzer" : "ik" 
     }, 
     "comment" : { 
      "type" : "string", 
      "analyzer" : "ik" 
     }, 
     "created_on" : { 
      "type" : "date", 
      "format" : "dateOptionalTime" 
     }, 
     "updated_on" : { 
      "type" : "date", 
      "format" : "dateOptionalTime" 
     }, 
     "custom": { 
      "type" : "nested", 
      "properties" : { 
      "key" : { 
       "type" : "string" 
      }, 
      "value" : { 
       "type" : "string" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Antwort

2

Eine einfache Möglichkeit, dies zu tun, ist es, einen eigenen Analysator zu schaffen, die Verwendung der Marken n-gram token filter für E-Mails (=> siehe unten index_email_analyzer und search_email_analyzer + email_url_analyzer für exakte E-Mail-Zuordnung) und edge-ngram token filter für Telefone (=> se e unter index_phone_analyzer und search_phone_analyzer).

Die vollständige Indexdefinition ist unten verfügbar.

PUT myindex 
{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "email_url_analyzer": { 
      "type": "custom", 
      "tokenizer": "uax_url_email", 
      "filter": [ "trim" ] 
     }, 
     "index_phone_analyzer": { 
      "type": "custom", 
      "char_filter": [ "digit_only" ], 
      "tokenizer": "digit_edge_ngram_tokenizer", 
      "filter": [ "trim" ] 
     }, 
     "search_phone_analyzer": { 
      "type": "custom", 
      "char_filter": [ "digit_only" ], 
      "tokenizer": "keyword", 
      "filter": [ "trim" ] 
     }, 
     "index_email_analyzer": { 
      "type": "custom", 
      "tokenizer": "standard", 
      "filter": [ "lowercase", "name_ngram_filter", "trim" ] 
     }, 
     "search_email_analyzer": { 
      "type": "custom", 
      "tokenizer": "standard", 
      "filter": [ "lowercase", "trim" ] 
     } 
     }, 
     "char_filter": { 
     "digit_only": { 
      "type": "pattern_replace", 
      "pattern": "\\D+", 
      "replacement": "" 
     } 
     }, 
     "tokenizer": { 
     "digit_edge_ngram_tokenizer": { 
      "type": "edgeNGram", 
      "min_gram": "1", 
      "max_gram": "15", 
      "token_chars": [ "digit" ] 
     } 
     }, 
     "filter": { 
     "name_ngram_filter": { 
      "type": "ngram", 
      "min_gram": "1", 
      "max_gram": "20" 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "your_type": { 
     "properties": { 
     "email": { 
      "type": "string", 
      "analyzer": "index_email_analyzer", 
      "search_analyzer": "search_email_analyzer" 
     }, 
     "phone": { 
      "type": "string", 
      "analyzer": "index_phone_analyzer", 
      "search_analyzer": "search_phone_analyzer" 
     } 
     } 
    } 
    } 
} 

Nun, lassen Sie uns es ein Stück nach dem anderen sezieren.

Für das Feld phone ist die Idee, Telefonwerte mit index_phone_analyzer zu indizieren, die einen Edge-Ngram Tokenizer verwendet, um alle Präfixe der Telefonnummer zu indizieren. Also, wenn Sie Ihre Telefonnummer 1362435647 ist, werden die folgenden Token erzeugt: 1, 13, 136, 1362, 13624, 136243, 1362435, 13624356, 13624356, 136243564, 1362435647.

Dann bei der Suche verwenden wir eine anderen Analysator search_phone_analyzer, die die Eingangsnummer einfach nehmen (zB 136) und gegen das phone Feld entsprechen eine einfache match oder term Abfrage:

POST myindex 
{ 
    "query": { 
     "term": 
      { "phone": "136" } 
    } 
} 

Für das email Feld, Wir gehen in ähnlicher Weise vor, indem wir die E-Mail-Werte mit der index_email_analyzer indexieren, die einen Ngram-Token-Filter verwendet, der alle möglichen Token unterschiedlicher Länge (zwischen 1 und 20 Zeichen) erzeugt, die aus dem E-Mail-Wert entnommen werden können. Zum Beispiel: [email protected] wird zu j, jo, joh, ..., gmail.com, ..., [email protected] tokenisiert.

Dann verwenden wir bei der Suche einen anderen Analyzer namens search_email_analyzer, der die Eingabe nimmt und versucht, sie mit den indizierten Token abzugleichen.

POST myindex 
{ 
    "query": { 
     "term": 
      { "email": "@gmail.com" } 
    } 
} 

Der email_url_analyzer Analysator wird in diesem Beispiel nicht verwendet, aber ich habe es nur enthalten, wenn Sie auf dem genauen E-Mail-Wert übereinstimmen müssen.

+0

WoW! Es ist erstaunlich! – pangpang

+0

Sie können die Min/Max-Parameter für das N-Gramm einstellen, aber dieses Setup unterstützt viele Suchfälle. – Val

+0

Wie sieht es mit der Leistung aus? – pangpang

Verwandte Themen