Come sfidare email o telefono di Elasticsearch?

Voglio fare confusione per email o telefono di Elasticsearch. Per esempio:

corrisponde a tutte le email e termina con @gmail.com

o

abbinare tutti gli avviamenti telefonici 136 .

So che posso usare il carattere jolly,

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

ma la performance è molto scarsa. Ho provato a usare regexp:

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

Ma non funziona.

C’è un modo migliore per farlo?

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": {} } } 

la mapping:

 { "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" } } } } } } } 

Un modo semplice per farlo è quello di creare un analizzatore personalizzato che utilizza il filtro token n-gram per le email (=> vedere sotto index_email_analyzer e search_email_analyzer + email_url_analyzer per la corrispondenza esatta delle e-mail) e il filtro token edge-ngram per i telefoni (=> vedi sotto index_phone_analyzer e search_phone_analyzer ).

La definizione dell’indice completa è disponibile sotto.

 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" } } } } } 

Ora, analizziamolo un po ‘dopo l’altro.

Per il campo phone , l’idea è di indicizzare i valori del telefono con index_phone_analyzer , che utilizza un tokenizzatore edge-ngram per indicizzare tutti i prefissi del numero di telefono. Quindi se il tuo numero di telefono è 1362435647 , verranno prodotti i seguenti token: 1 , 13 , 136 , 1362 , 13624 , 136243 , 1362435 , 13624356 , 13624356 , 136243564 , 1362435647 .

Quindi, durante la ricerca, utilizziamo un altro analizzatore search_phone_analyzer che prenderà semplicemente il numero di input (ad es. 136 ) e lo search_phone_analyzer al campo del phone utilizzando una semplice match o query di term :

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

Per il campo email , procediamo in modo simile, in quanto indicizziamo i valori email con index_email_analyzer , che utilizza un filtro token ngram, che produrrà tutti i token possibili di lunghezza variabile (tra 1 e 20 caratteri) che possono essere presi dal valore dell’e-mail. Ad esempio: [email protected] sarà tokenizzato a j , jo , joh , …, gmail.com , …, [email protected] .

Quindi, durante la ricerca, utilizzeremo un altro analizzatore chiamato search_email_analyzer che prenderà l’input e cercherà di farlo corrispondere ai token indicizzati.

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

L’analizzatore email_url_analyzer non è utilizzato in questo esempio ma l’ho incluso solo nel caso in cui sia necessario abbinare il valore esatto del messaggio.