Mysql
 sql >> Database >  >> RDS >> Mysql

Come abbinare e-mail o telefono fuzzy con Elasticsearch?

Un modo semplice per farlo è creare un analizzatore personalizzato che utilizzi filtro token n-gram per le email (=> vedi sotto index_email_analyzer e search_email_analyzer + email_url_analyzer per l'esatta corrispondenza e-mail) e edge-ngram filtro token per telefoni (=> vedi sotto index_phone_analyzer e search_phone_analyzer ).

La definizione completa dell'indice è disponibile di seguito.

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 phone campo, 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 confrontalo con il phone campo utilizzando una semplice match o term domanda:

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

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

Quindi, durante la ricerca, utilizzeremo un altro analizzatore chiamato search_email_analyzer che prenderà l'input e proverà a confrontarlo con i token indicizzati.

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

L'email_url_analyzer Analyzer non viene utilizzato in questo esempio, ma l'ho incluso nel caso in cui sia necessario corrispondere al valore esatto dell'e-mail.