Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En las soluciones de búsqueda, las cadenas que tienen patrones complejos o caracteres especiales pueden resultar difíciles de trabajar porque el analizador predeterminado quita o interpreta mal partes significativas de un patrón. Esto da como resultado una mala experiencia de búsqueda en la que los usuarios no pueden encontrar la información que esperan. Los números de teléfono son un ejemplo clásico de cadenas que son difíciles de analizar. Vienen en varios formatos e incluyen caracteres especiales que el analizador predeterminado omite.
Con los números de teléfono como asunto, en este tutorial se usan las API REST del servicio de búsqueda para resolver problemas de datos con patrones mediante un analizador personalizado. Este enfoque se puede usar tal como está para números de teléfono o adaptados para campos con las mismas características (patrón con caracteres especiales), como direcciones URL, correos electrónicos, códigos postales y fechas.
En este tutorial, usted hará lo siguiente:
- Comprender el problema
- Desarrollar un analizador personalizado inicial para controlar números de teléfono
- Probar el analizador personalizado
- Iterar el diseño del analizador personalizado para mejorar aún más los resultados
Requisitos previos
Una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.
Descarga de archivos
El código fuente de este tutorial se encuentra en el archivo custom-analyzer.rest del repositorio de GitHub Azure-Samples/azure-search-rest-samples .
Copia de una clave de administrador y una dirección URL
Las llamadas REST de este tutorial requieren un punto de conexión de servicio de búsqueda y una clave de API de administración. Puede obtener estos valores en Azure Portal.
Inicie sesión en Azure Portal y seleccione el servicio de búsqueda.
En el panel izquierdo, seleccione Información general y copie el punto de conexión. Debe tener este formato:
https://my-service.search.windows.netEn el panel izquierdo, seleccioneClaves de > y copie una clave de administrador para obtener derechos completos en el servicio. Hay dos claves de administración intercambiables, proporcionadas para la continuidad empresarial en caso de que necesite revertir una. Puede usar cualquiera de las claves en las solicitudes para agregar, modificar o eliminar objetos.
Creación de un índice inicial
Abra un nuevo archivo de texto en Visual Studio Code.
Establezca variables en el punto de conexión de búsqueda y la clave de API que recopiló en la sección anterior.
@baseUrl = PUT-YOUR-SEARCH-SERVICE-URL-HERE @apiKey = PUT-YOUR-ADMIN-API-KEY-HEREGuarde el archivo con una extensión de archivo
.rest.Pegue el ejemplo siguiente para crear un índice pequeño denominado
phone-numbers-indexcon dos campos:idyphone_number.### Create a new index POST {{baseUrl}}/indexes?api-version=2025-09-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "phone-numbers-index", "fields": [ { "name": "id", "type": "Edm.String", "key": true, "searchable": true, "filterable": false, "facetable": false, "sortable": true }, { "name": "phone_number", "type": "Edm.String", "sortable": false, "searchable": true, "filterable": false, "facetable": false } ] }Todavía no ha definido un analizador, por lo que el
standard.luceneanalizador se usa de forma predeterminada.Seleccione Enviar solicitud. Debe tener una respuesta
HTTP/1.1 201 Createdy el cuerpo de la respuesta debe incluir la representación JSON del esquema de índice.Cargue datos en el índice mediante documentos que contienen varios formatos de número de teléfono. Estos son los datos de prueba.
### Load documents POST {{baseUrl}}/indexes/phone-numbers-index/docs/index?api-version=2025-09-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "value": [ { "@search.action": "upload", "id": "1", "phone_number": "425-555-0100" }, { "@search.action": "upload", "id": "2", "phone_number": "(321) 555-0199" }, { "@search.action": "upload", "id": "3", "phone_number": "+1 425-555-0100" }, { "@search.action": "upload", "id": "4", "phone_number": "+1 (321) 555-0199" }, { "@search.action": "upload", "id": "5", "phone_number": "4255550100" }, { "@search.action": "upload", "id": "6", "phone_number": "13215550199" }, { "@search.action": "upload", "id": "7", "phone_number": "425 555 0100" }, { "@search.action": "upload", "id": "8", "phone_number": "321.555.0199" } ] }Pruebe las consultas similares a las que un usuario podría escribir. Por ejemplo, un usuario podría buscar
(425) 555-0100en cualquier número de formatos y esperar que se devuelvan los resultados. Empiece por buscar en(425) 555-0100.### Search for a phone number POST {{baseUrl}}/indexes/phone-numbers-index/docs/search?api-version=2025-09-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "search": "(425) 555-0100" }La consulta devuelve tres de cuatro resultados esperados, pero también devuelve dos resultados inesperados.
{ "value": [ { "@search.score": 0.05634898, "phone_number": "+1 425-555-0100" }, { "@search.score": 0.05634898, "phone_number": "425 555 0100" }, { "@search.score": 0.05634898, "phone_number": "425-555-0100" }, { "@search.score": 0.020766128, "phone_number": "(321) 555-0199" }, { "@search.score": 0.020766128, "phone_number": "+1 (321) 555-0199" } ] }Inténtelo de nuevo sin ningún formato:
4255550100.### Search for a phone number POST {{baseUrl}}/indexes/phone-numbers-index/docs/search?api-version=2025-09-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "search": "4255550100" }Esta consulta todavía es peor y solo devuelve una de las cuatro coincidencias correctas.
{ "value": [ { "@search.score": 0.6015292, "phone_number": "4255550100" } ] }
Si encuentra confusos estos resultados, no es el único. En la sección siguiente se explica por qué obtiene estos resultados.
Revisión del funcionamiento de los analizadores
Para comprender estos resultados de búsqueda, debe comprender lo que hace el analizador. Desde allí, puede probar el analizador predeterminado mediante Analyze API, lo que proporciona una base para diseñar un analizador que satisfaga mejor sus necesidades.
Un analizador es un componente del motor de búsqueda de texto completo responsable de procesar texto en cadenas de consulta y documentos indexados. Diferentes analizadores manipulan el texto de maneras diferentes según el escenario. En este escenario, es necesario crear un analizador adaptado a los números de teléfono.
Los analizadores constan de tres componentes:
- Filtros de caracteres que eliminan o sustituyen caracteres individuales del texto introducido.
- Tokenizador que divide el texto de entrada en tokens, que se convierten en claves en el índice de búsqueda.
- Filtros de tokens que manipulan los tokens producidos por el tokenizador.
En el diagrama siguiente se muestra cómo funcionan juntos estos tres componentes para tokenizar una oración.
Estos tokens se almacenan en un índice invertido, lo que permite búsquedas rápidas y de texto completo. Un índice invertido permite la búsqueda de texto completo mediante la asignación de todos los términos únicos extraídos durante el análisis léxico a los documentos en los que se producen. Puede ver un ejemplo en el diagrama siguiente:
Toda la búsqueda se reduce a buscar los términos almacenados en el índice invertido. El usuario emite una consulta:
- Se analizan la consulta y sus términos.
- El índice invertido se revisa en busca de documentos con términos coincidentes.
- El algoritmo de puntuación clasifica los documentos recuperados.
Si los términos de la consulta no coinciden con los términos del índice invertido, no se devuelven resultados. Para más información sobre cómo funcionan las consultas, consulte Búsqueda de texto completo en Azure AI Search.
Nota:
Las consultas de términos parciales son una excepción importante para esta regla. A diferencia de las consultas de términos normales, estas consultas (consulta de prefijo, consulta comodín y consulta regex) omiten el proceso de análisis léxico. Los términos parciales solo están en minúsculas antes de que coincidan con los términos del índice. Si un analizador no está configurado para admitir estos tipos de consultas, a menudo recibe resultados inesperados porque los términos coincidentes no existen en el índice.
Análisis de analizadores mediante la API de análisis
Búsqueda de Azure AI ofrece la API de análisis que permite probar los analizadores para comprender cómo procesan el texto.
Llame a analyze API mediante la solicitud siguiente:
### Test analyzer
POST {{baseUrl}}/indexes/phone-numbers-index/analyze?api-version=2025-09-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
{
"text": "(425) 555-0100",
"analyzer": "standard.lucene"
}
La API devuelve los tokens extraídos del texto mediante el analizador especificado. El analizador estándar de Lucene divide el número de teléfono en tres tokens independientes.
{
"tokens": [
{
"token": "425",
"startOffset": 1,
"endOffset": 4,
"position": 0
},
{
"token": "555",
"startOffset": 6,
"endOffset": 9,
"position": 1
},
{
"token": "0100",
"startOffset": 10,
"endOffset": 14,
"position": 2
}
]
}
Por el contrario, el número de teléfono 4255550100 con formato sin puntuación se tokeniza en un token único.
{
"text": "4255550100",
"analyzer": "standard.lucene"
}
Respuesta:
{
"tokens": [
{
"token": "4255550100",
"startOffset": 0,
"endOffset": 10,
"position": 0
}
]
}
Tenga en cuenta que tanto los términos de consulta como los documentos indizado se someten a análisis. Pensando en los resultados de búsqueda del paso anterior, puede empezar a ver por qué se devuelven esos resultados.
En la primera consulta, se devuelven números de teléfono inesperados porque uno de sus tokens, 555, coincide con uno de los términos que ha buscado. En la segunda consulta, solo se devuelve un número porque es el único registro que tiene un token que coincide con 4255550100.
Creación de un analizador personalizado
Ahora que comprende los resultados que está viendo, cree un analizador personalizado para mejorar la lógica de tokenización.
El objetivo es proporcionar una búsqueda intuitiva en los números de teléfono, independientemente del formato en el que se encuentre la consulta o la cadena indexada. Para lograr este resultado, especifique un filtro de caracteres, un tokenizador y un filtro de token.
Filtros de caracteres
Los filtros de caracteres procesan el texto antes de introducirlo en el tokenizador. Los usos comunes de los filtros de caracteres son filtrar elementos HTML y reemplazar caracteres especiales.
En el caso de los números de teléfono, quiere quitar espacios en blanco y caracteres especiales, ya que no todos los formatos de número de teléfono contienen los mismos caracteres y espacios especiales.
"charFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.MappingCharFilter",
"name": "phone_char_mapping",
"mappings": [
"-=>",
"(=>",
")=>",
"+=>",
".=>",
"\\u0020=>"
]
}
]
El filtro quita -()+. y espacios de la entrada.
| Entrada | Salida |
|---|---|
(321) 555-0199 |
3215550199 |
321.555.0199 |
3215550199 |
Tokenizer
Los tokenizadores dividen el texto en tokens y descartan algunos caracteres, como los signos de puntuación, a lo largo del proceso. En muchos casos, el objetivo de la tokenización es dividir una frase en palabras individuales.
En este escenario, use un tokenizador de palabra clave, keyword_v2, para capturar el número de teléfono como un solo término. Esta no es la única manera de resolver este problema, como se explica en la sección Enfoques alternativos .
Los tokenizadores de palabras clave siempre generan el mismo texto que se les proporciona como un solo término.
| Entrada | Salida |
|---|---|
The dog swims. |
[The dog swims.] |
3215550199 |
[3215550199] |
Filtros de token
Los filtros de token modifican o filtran los tokens generados por el tokenizador. Un uso habitual de un filtro de token es poner en minúsculas todos los caracteres mediante un filtro de token en minúsculas. Otro uso común es filtrar palabras irrelevantes, como the, ando is.
Aunque no es necesario usar ninguno de esos filtros para este escenario, use un filtro de token de nGram para permitir búsquedas parciales de números de teléfono.
"tokenFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.NGramTokenFilterV2",
"name": "custom_ngram_filter",
"minGram": 3,
"maxGram": 20
}
]
NGramTokenFilterV2
El filtro de token nGram_v2 divide los tokens en n-gramas de un tamaño determinado basándose en los parámetros minGram y maxGram.
Para el analizador de teléfonos, minGram se establece en 3 porque se espera que los usuarios busquen la subcadena más corta.
maxGram se establece en 20 para asegurarse de que todos los números de teléfono, incluso con extensiones, caben en un solo n-grama.
El efecto secundario no deseado de los n-gramas es que se devuelven algunos falsos positivos. Esto se corrige en un paso posterior mediante la creación de un analizador independiente para búsquedas que no incluyan el filtro de token de n-grama.
| Entrada | Salida |
|---|---|
[12345] |
[123, 1234, 12345, 234, 2345, 345] |
[3215550199] |
[321, 3215, 32155, 321555, 3215550, 32155501, 321555019, 3215550199, 215, 2155, 21555, 215550, ... ] |
Analizador
Con los filtros de caracteres, el tokenizador y los filtros de token implementados, está listo para definir el analizador.
"analyzers": [
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer",
"tokenizer": "keyword_v2",
"tokenFilters": [
"custom_ngram_filter"
],
"charFilters": [
"phone_char_mapping"
]
}
]
En Analyze API, dadas las siguientes entradas, las salidas del analizador personalizado son las siguientes:
| Entrada | Salida |
|---|---|
12345 |
[123, 1234, 12345, 234, 2345, 345] |
(321) 555-0199 |
[321, 3215, 32155, 321555, 3215550, 32155501, 321555019, 3215550199, 215, 2155, 21555, 215550, ... ] |
Todos los tokens de la columna de salida existen en el índice. Si la consulta incluye cualquiera de esos términos, se devuelve el número de teléfono.
Recompilación mediante el nuevo analizador
Elimine el índice actual.
### Delete the index DELETE {{baseUrl}}/indexes/phone-numbers-index?api-version=2025-09-01 HTTP/1.1 api-key: {{apiKey}}Vuelva a crear el índice mediante el nuevo analizador. Este esquema de índice agrega una definición de analizador personalizada y una asignación de analizador personalizada en el campo número de teléfono.
### Create a new index POST {{baseUrl}}/indexes?api-version=2025-09-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "phone-numbers-index-2", "fields": [ { "name": "id", "type": "Edm.String", "key": true, "searchable": true, "filterable": false, "facetable": false, "sortable": true }, { "name": "phone_number", "type": "Edm.String", "sortable": false, "searchable": true, "filterable": false, "facetable": false, "analyzer": "phone_analyzer" } ], "analyzers": [ { "@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer", "name": "phone_analyzer", "tokenizer": "keyword_v2", "tokenFilters": [ "custom_ngram_filter" ], "charFilters": [ "phone_char_mapping" ] } ], "charFilters": [ { "@odata.type": "#Microsoft.Azure.Search.MappingCharFilter", "name": "phone_char_mapping", "mappings": [ "-=>", "(=>", ")=>", "+=>", ".=>", "\\u0020=>" ] } ], "tokenFilters": [ { "@odata.type": "#Microsoft.Azure.Search.NGramTokenFilterV2", "name": "custom_ngram_filter", "minGram": 3, "maxGram": 20 } ] }
Probar el analizador personalizado
Después de volver a crear el índice, pruebe el analizador mediante la solicitud siguiente:
### Test custom analyzer
POST {{baseUrl}}/indexes/phone-numbers-index-2/analyze?api-version=2025-09-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
{
"text": "+1 (321) 555-0199",
"analyzer": "phone_analyzer"
}
Ahora debería ver la colección de tokens resultantes del número de teléfono.
{
"tokens": [
{
"token": "132",
"startOffset": 1,
"endOffset": 17,
"position": 0
},
{
"token": "1321",
"startOffset": 1,
"endOffset": 17,
"position": 0
},
{
"token": "13215",
"startOffset": 1,
"endOffset": 17,
"position": 0
},
...
...
...
]
}
Revisión del analizador personalizado para controlar falsos positivos
Después de usar el analizador personalizado para realizar consultas de ejemplo en el índice, debería ver que la recuperación ha mejorado y se devuelven todos los números de teléfono coincidentes. Sin embargo, el filtro de token de n-grama provoca que también se devuelvan algunos falsos positivos. Se trata de un efecto secundario frecuente de un filtro de token de n-grama.
Para evitar falsos positivos, cree un analizador independiente para realizar consultas. Este analizador es idéntico al anterior, salvo que omite .custom_ngram_filter
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer_search",
"tokenizer": "custom_tokenizer_phone",
"tokenFilters": [],
"charFilters": [
"phone_char_mapping"
]
}
En la definición del índice, especifique tanto un indexAnalyzer como un searchAnalyzer.
{
"name": "phone_number",
"type": "Edm.String",
"sortable": false,
"searchable": true,
"filterable": false,
"facetable": false,
"indexAnalyzer": "phone_analyzer",
"searchAnalyzer": "phone_analyzer_search"
}
Con este cambio, está todo listo. Estos son los pasos siguientes:
Elimina el índice.
Vuelva a crear el índice después de agregar el nuevo analizador personalizado (
phone_analyzer-search) y asígnelo a la propiedadphone-numberdel camposearchAnalyzer.Vuelva a cargar los datos.
Vuelva a probar las consultas para comprobar que la búsqueda funciona según lo previsto. Si usa el archivo de ejemplo, este paso crea el tercer índice denominado
phone-number-index-3.
Enfoques alternativos
El analizador descrito en la sección anterior está diseñado para maximizar la flexibilidad de la búsqueda. Sin embargo, esto es a expensas del costo que supone el almacenamiento en el índice de muchos términos que pueden no ser importantes.
En el ejemplo siguiente se muestra un analizador alternativo que es más eficaz en la tokenización, pero tiene inconvenientes.
Dada una entrada de 14255550100, el analizador no puede fragmentar lógicamente el número de teléfono. Por ejemplo, no puede separar el código de país, 1, del código de área, 425. Esta discrepancia conduce a que no se devuelva el número de teléfono si un usuario no incluye un código de país en su búsqueda.
"analyzers": [
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer_shingles",
"tokenizer": "custom_tokenizer_phone",
"tokenFilters": [
"custom_shingle_filter"
]
}
],
"tokenizers": [
{
"@odata.type": "#Microsoft.Azure.Search.StandardTokenizerV2",
"name": "custom_tokenizer_phone",
"maxTokenLength": 4
}
],
"tokenFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.ShingleTokenFilter",
"name": "custom_shingle_filter",
"minShingleSize": 2,
"maxShingleSize": 6,
"tokenSeparator": ""
}
]
En el siguiente ejemplo, el número de teléfono se divide en los fragmentos que normalmente se espera que un usuario los busque.
| Entrada | Salida |
|---|---|
(321) 555-0199 |
[321, 555, 0199, 321555, 5550199, 3215550199] |
En función de sus requisitos, este puede ser un enfoque más eficaz del problema.
Puntos clave
En este tutorial se muestra el proceso de creación y prueba de un analizador personalizado. Ha creado un índice, ha indexado los datos y, a continuación, ha consultado en el índice para ver los resultados de búsqueda que se han devuelto. Con esto, ha usado la API de análisis para ver el proceso de análisis léxico en acción.
Aunque el analizador definido en este tutorial ofrece una solución sencilla para buscar números de teléfono, este mismo proceso se puede usar para crear un analizador personalizado para cualquier escenario que comparta características similares.
Limpieza de recursos
Cuando trabaje con su propia suscripción, al final de un proyecto, es recomendable eliminar los recursos que ya no necesite. Los recursos que se dejan en ejecución pueden costarle mucho dinero. Puede eliminar los recursos de forma individual o eliminar el grupo de recursos para eliminar todo el conjunto de recursos.
Puede buscar y administrar los recursos en Azure Portal, mediante el vínculo Todos los recursos o Grupos de recursos en el panel de navegación izquierdo.
Pasos siguientes
Ahora que sabe cómo crear un analizador personalizado, eche un vistazo a todos los distintos filtros, tokenizadores y analizadores disponibles para crear una experiencia de búsqueda enriquecida: