sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo hacer una coincidencia aproximada de correo electrónico o teléfono por Elasticsearch?

Una manera fácil de hacer esto es crear un analizador personalizado que utilice el filtro de token n-gram para correos electrónicos (=> ver a continuación index_email_analyzer y search_email_analyzer + email_url_analyzer para la coincidencia exacta de correo electrónico) y edge-ngram filtro de fichas para teléfonos (=> ver a continuación index_phone_analyzer y search_phone_analyzer ).

La definición completa del índice está disponible a continuación.

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

Ahora, vamos a diseccionarlo un poco tras otro.

Para el phone campo, la idea es indexar los valores del teléfono con index_phone_analyzer , que utiliza un tokenizador edge-ngram para indexar todos los prefijos del número de teléfono. Entonces, si su número de teléfono es 1362435647 , se producirán los siguientes tokens:1 , 13 , 136 , 1362 , 13624 , 136243 , 1362435 , 13624356 , 13624356 , 136243564 , 1362435647 .

Luego, cuando buscamos, usamos otro analizador search_phone_analyzer que simplemente tomará el número de entrada (por ejemplo, 136 ) y compararlo con el phone campo usando una simple match o term consulta:

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

Para el email Procedemos de manera similar, en el sentido de que indexamos los valores de correo electrónico con el index_email_analyzer , que utiliza un filtro de token de ngram, que producirá todos los tokens posibles de longitud variable (entre 1 y 20 caracteres) que se pueden tomar del valor del correo electrónico. Por ejemplo:[email protected] será tokenizado a j , jo , joh , ..., gmail.com , ..., [email protected] .

Luego, al buscar, usaremos otro analizador llamado search_email_analyzer que tomará la entrada e intentará compararla con los tokens indexados.

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

El email_url_analyzer El analizador no se usa en este ejemplo, pero lo he incluido en caso de que necesite hacer coincidir el valor exacto del correo electrónico.