Búsqueda de texto completo

Búsqueda y rescate: 7 razones por las que los desarrolladores de N1QL utilizan la búsqueda


La gente no quiere un índice de cuatro teclas. Necesitan una respuesta de cuatro ms.

Ted Levitt

El desarrollo de aplicaciones es exigente. Cada aplicación intenta avanzar en nombre del cliente: buscar el producto o el formulario adecuados, hacer pedidos, cancelarlos, enviarlos, comprobar su estado, etc.

Las bases de datos y la infraestructura típicas basadas en consultas y B-Tree son adecuadas para desarrollar muchos de los módulos. Aun así, hay casos en los que la búsqueda basada en SQL y B-Tree resulta ineficaz para cumplir su SLA.

Aquí están los siete problemas que encontrarías en el desarrollo de SQL y las soluciones para ellos usando la tecnología de Búsqueda. He usado Couchbase N1QL como ejemplo de implementación SQL, Couchbase GSI como ejemplo de índices basados en B-Tree (lógicamente hablando) y FTS (Couchbase Full-Text Search) como ejemplo de tecnología de búsqueda.

También utilizaré el viaje-muestra y los datos del conjunto de datos de muestra de Couchbase en los ejemplos.

Retos para los desarrolladores

1. El problema de búsqueda de NOMBRE (también conocido como el problema LIKE)

A los medios sociales les puede gustar como a menudo, pero SQL no. Los predicados LIKE son una de las primeras cosas que hay que tener en cuenta cuando se utilizan en una consulta. Sin un uso cuidadoso, el predicado LIKE aumentará la latencia, reducirá el rendimiento y bloqueará la operación. He aquí un ejemplo de predicados LIKE que he visto en aplicaciones reales de clientes.

  • WHERE nombre LIKE "%joe%";
  • WHERE UPPER(nombre) LIKE "%JOE%"
  • WHERE REGEX_CONTAINS(nombre, ".*joe.*")
  • WHERE nombre LIKE "% joe %"

Problemas:

  • Incluso cuando tenga un índice sobre el nombre, tendrá que escanear todo el índice para determinar todos los documentos con joe.
  • Tendrías que crear un índice funcional (por ejemplo, UPPER(nombre)) y tener la clave adicional con el nombre para guardar el caso exacto del nombre. Por ejemplo, McDonald
  • Con los tres primeros predicados, no sólo obtendrá joe, sino también las cadenas joel, sojoel, bejoel, etc.

2. El problema de los partidos múltiples

Cuando los nombres se dividen en nombre, segundo nombre y apellido, hay que buscar en todas partes. A veces, querrás buscar una cadena en cualquiera de los nombres. Combina eso con la búsqueda de su número de llamada. Su consulta será algo parecido a esto.


SELECT c.customerid, c.fname, c.mname, c.lname, c.address
DESDE cliente c
WHERE (c.fname in ['John', 'Doe']
     OR c.mname in ['John', 'Doe']
     OR c.lname in ['John', 'Doe'])
     OR (ANY p in c.contacts satisfies p = '6509264813')
     OR (ANY q in c.services satisfies q = '6509264813')

Ahora, intenta crear un índice B-TREE que te proporcione no sólo la baja latencia que deseas, sino también un alto rendimiento.  

3. Más allá de la coincidencia exacta

Los partidos del mundo real son inexactos. William puede abreviarse como Will, Willy, Bill y Billy. Los irlandeses y los escoceses tienen abreviaturas adicionales. ¿Cómo se puede buscar Billy y acabar con William?


4. Búsqueda basada en los requisitos de la empresa

Cada empresa tiene normas sobre la resolución de la información del cliente (nombre, dirección y fecha de nacimiento) a un cliente en particular. Algunas dan más prioridad a la dirección que al nombre o la dirección. Las reglas pueden decir, los dos de cuatro tendrá que ser una coincidencia exacta y otros tienen que ser una coincidencia parcial. Los predicados N1QL se vuelven aún más complejos que en el segundo caso. Por lo tanto, el índice GSI adecuado para la consulta también se complica.

5. Ordenación por relevancia

El orden de N1QL se basa en la cláusula ORDER BY y la expresión dentro de ella. Cuando se hace una coincidencia inexacta, es posible que desee el orden basado en la puntuación del texto y la distancia desde el patrón de búsqueda dado.

6. El problema de la matriz.

Las matrices JSON te ofrecen la posibilidad de almacenar las relaciones 1:N, N:M como una matriz de objetos o matrices con enlaces a otros objetos. Este artículo le ofrece detalles sobre la manipulación de matrices. La página segundo artículo describe operaciones adicionales orientadas a conjuntos sobre matrices. Para obtener el mejor rendimiento al buscar dentro de matrices, es necesario crear índices con claves de matriz. El índice de matriz tiene una limitación: cada índice de matriz sólo puede tener una clave de matriz por índice. Por lo tanto, si tienes un objeto cliente con varios campos de matriz, no puedes buscar en todos ellos utilizando un único índice. Cuando tienes clientes con un array de números de contacto y un array de contactos de correo electrónico, no puedes buscar por ambos utilizando un único índice, lo que provoca consultas costosas. Se trata de una limitación común de los índices de matrices basados en árboles b. Dado que el índice del árbol B almacena los elementos individuales de la matriz como claves distintas, al tener varias claves de matriz será necesario que el índice almacene el producto del número de claves (en el ejemplo anterior, (número de números de contacto) * (número de correos electrónicos). El tamaño del índice aumentará exponencialmente. Para evitar esto, los productos deshabilitan la creación de múltiples claves de array para un único índice.

Pero, el trabajo del desarrollador para buscar eficientemente en múltiples matrices JSON permanece.

7. Consultas múltiples, índice único.

El modelo JSON se ha utilizado con éxito para agregar información de múltiples fuentes. El objetivo de agregar toda esta información no es simplemente almacenarla, sino consultarla y obtener valor empresarial. Cuando se tiene una consulta ad-hoc sobre un conjunto de datos, es difícil planificar previamente y volver a crear los índices necesarios para ello. El propio N1QL proporciona el índice adaptativo que ayuda en determinados casos de uso. Si tiene varios predicados, cada uno de los cuales puede devolver un conjunto de resultados grande, el índice adaptativo tendrá problemas de rendimiento debido a la cantidad de transferencia de datos del índice al nodo de consulta y al gran conjunto de resultados intermedios.

En este caso, los desarrolladores deben supervisar y ajustar continuamente los índices. Los usuarios con problemas de rendimiento seguirán quejándose.

 

Soluciones:

1.El problema de búsqueda de NOMBRE (también conocido como problema LIKE)

Tanto si busca joe, Joel o jolly, todas suelen ser palabras sueltas. Normalmente no se busca lajoella. El índice de búsqueda toma cada palabra de su campo (nombre, título o comentario), la analiza en función de las características lingüísticas, clasifica las palabras en stop words (palabras vacías y que no suelen buscarse - por ejemplo: and, or, not, the en inglés) y términos. Indexar el término en lugar de la palabra propiamente dicha tiene dos ventajas.

  1. Agrupa las palabras relacionadas: francisco, francisco, frank, francoisetc. Al buscar francisco, también encontrará palabras estrechamente relacionadas francisco.
  2. Esta agrupación también reducirá el tamaño del índice, ya que sólo tendremos que indexar el término raíz en lugar de todos los modificadores de esa palabra.

Volvamos a la búsqueda del nombre: Busquemos ahora el nombre del hotel.

  1. Crear un índice FTS en documentos de tipo hotel y el campo nombre en el documento.
  2. Empieza a buscar el nombre:
    • Aquí está la consulta a ejecutar:

curl -XPOST -H "Content-Type: application/json" \ http://172.23.120.38:8094/api/index/trhotelname/query \ -d '{ "explain": true, "fields": [ "*" ], "highlight": {}, "query": { "query": "francisco" } }'

  1. Búsqueda de francisco te da los nombres de los hoteles:
      • "name": "The Opal San Francisco",
      • "name": "Francisco Bay Inn",
      • y mucho más (11 resultados en total).
      •  

2. El problema de los partidos múltiples

Antes vimos la consulta compleja.

SELECT c.customerid, c.fname, c.mname, c.lname, c.address
DESDE cliente c
WHERE (c.fname in ['John', 'Doe']
     OR c.mname in ['John', 'Doe']
     OR c.lname in ['John', 'Doe'])
     OR (ANY p in c.contacts satisfies p = '6509264813')
     OR (ANY q in c.services satisfies q = '6509264813')

En FTS, podemos definir un campo especial _all que combina varios campos. La búsqueda en este índice busca automáticamente en TODOS los campos. (Véase también este artículo) Se trata de un índice sobre cinco campos del documento del hotel:

  1. ciudad
  2. país
  3. nombre
  4. public_likes (un campo de matriz)
  5. descripción

Ejemplos de valores para los cinco campos:

[
{
"ciudad": "Medway",
"país": "Reino Unido",
"Descripción": "Albergue de verano de 40 camas a unos 5 km de Gillingham, ubicado en una característica Oast House reconvertida en un entorno semirural.",
"name": "Albergue Juvenil Medway",
"public_likes": [
"Julius Tromp I",
"Corrine Hilll",
"Jaeden McKenzie",
"Vallie Ryan",
"Brian Kilback",
"Lilian McLaughlin",
"Sra. Moses Feeney",
"Elnora Trantow"
]
}
]

Una vez que defina el índice de búsqueda en todos estos campos, simplemente empiece a consultar.

 

 

 

 

Esta es la definición de índice para el índice de campo _all utilizado aquí.

 

 

 

3. Más allá de la coincidencia exacta

Search (FTS) hace más que una búsqueda exacta. Realiza la búsqueda de términos, la búsqueda de rangos, la búsqueda difusa, conjuntos, disjuntos, geo-búsqueda (vecino más cercano), búsqueda regex, búsqueda potenciada, búsqueda de frases y mucho más. Vea ejemplos y detalles en Documentación de Couchbase FTS.

4.Búsqueda basada en los requisitos de su empresa

Cuando busque hoteles en Nueva York, es posible que prefiera los hoteles de Manhattan, pero que quiera ver también otros hoteles. Para ello, basta con potenciar el término de búsqueda Manhattan añadiendo ^5. Esta potenciación mejora la puntuación de los documentos que contienen Manhattan. Los resultados se ordenan por defecto en orden descendente de puntuación.

5. Ordenación por relevancia

En SQL, la ordenación se basa en el valor de la expresión o del propio campo. En la búsqueda, la relevancia de un documento se calcula por la distancia entre lo que se busca y lo que contiene el documento. Esta es la puntuación que manipulamos al aumentar la importancia de un término en la sección anterior. Puede ordenar los resultados por esta puntuación y cualquier otro campo utilizando la cláusula de ordenación de la petición de búsqueda.

6. El problema de las matrices

Ahora, vamos a crear un índice único en las siguientes cuatro matrices.

  1. me gusta_público
  2. reseñas.autor
  3. reviews.ratings.Location
  4. reseñas.valoraciones.Servicio

Aquí está la definición del índice. Se trata de un índice único sobre cuatro claves de matriz. Esto es algo que nunca se podría hacer en un índice basado en un árbol B.

Ahora puede realizar consultas utilizando predicados en uno o varios de los campos anteriores.

EJEMPLO 1: hoteles que le gustan a "Vallie Ryan" o valoración del servicio superior a 4

‘{
"explicar": true,
"fields": [ "*" ],
"highlight": {},
"query": {"query": "+public_likes:\"Vallie Ryan\" reviews.ratings.Service:>4″ }
}’

Índice completo Definición.

 

7.Consultas múltiples, índice único.

"A veces, las consultas son como una caja de bombones. No sabes qué consulta vas a recibir". Cuando se desea exponer los datos a usuarios empresariales que pueden realizar consultas ad hoc, no se puede crear cualquier tipo de índice para acelerar cualquier tipo de consulta. El ajuste del rendimiento requiere un enfoque diferente.

Considere el índice creado en la sección (2) anterior sobre los 5 campos:

  1. ciudad
  2. país
  3. nombre
  4. public_likes (un campo de matriz)
  5. descripción

Si creara un árbol B (índice GSI en el caso de Couchbsae), tendría el siguiente aspecto:

CREAR ÍNDICE itravel EN viaje-muestra(ciudad, país, nombre, DISTINCT public_likes, descripción) WHERE type = 'hotel';

Las consultas que se beneficiarían de ello son las siguientes normas explicadas aquí. El principal problema es que cada bloque de consulta (en concreto, la exploración del índice) tendrá que utilizar predicados en la(s) clave(s) principal(es) del índice. Esto limita la eficacia del índice.

Con el índice search(FTS) creado anteriormente, puedes realizar consultas basadas en cualquier conjunción, disyunción, must have, etc con cualquier combinación. Con consultas complejas, la búsqueda puede tardar más de unos pocos milisegundos, pero estás haciendo todo esto en un solo índice. La flexibilidad con un uso razonable de los recursos hace que el índice de búsqueda sea muy valioso.

Nota: En la próxima versión 6.5 de Couchbase, hemos facilitado la consulta utilizando el índice de búsqueda. Binh Le lo ha explicado en este artículo:https://www.couchbase.com/blog/n1ql-and-search-how-to-leverage-fts-index-in-n1ql-query/

Referencias

 

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Keshav Murthy

Keshav Murthy es Vicepresidente de Couchbase R&D. Anteriormente, estuvo en MapR, IBM, Informix, Sybase, con más de 20 años de experiencia en diseño y desarrollo de bases de datos. Dirigió el equipo de I+D de SQL y NoSQL en IBM Informix. Ha recibido dos premios President's Club en Couchbase y dos premios Outstanding Technical Achievement en IBM. Keshav es licenciado en Informática e Ingeniería por la Universidad de Mysore (India), es titular de diez patentes estadounidenses y tiene tres pendientes.

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.