Obtenga coincidencia parcial de la columna TSVECTOR indexada a GIN


13

Me gustaría obtener resultados al consultar esto:

SELECT * FROM (
  SELECT id, subject
  FROM mailboxes
  WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;

Esto funciona y devuelve filas con tsvcontener Available. Pero si uso avai(se cayó lable) no puede encontrar nada.

¿Todas las consultas tienen que estar en el diccionario? ¿No podemos simplemente consultar esas letras? Tengo una base de datos que contiene el cuerpo del correo electrónico (contenido) y me gustaría hacerlo rápido a medida que crece cada segundo. Actualmente estoy usando

... WHERE content ~* 'letters`

Respuestas:


22

¿Todas las consultas tienen que estar en el diccionario?

No. Debido a que solo los tallos de palabras (de acuerdo con la configuración de búsqueda de texto utilizada ) están en el índice para empezar. Pero mas importante:

No se . Porque, además de eso, la búsqueda de texto completo también es capaz de coincidir con prefijos :

Esto funcionaría:

SELECT id, subject
FROM   mailboxes
WHERE  tsv @@ to_tsquery('simple', 'avail:*')
ORDER  BY id DESC;

Nota 3 cosas:

  1. Use to_tsquery(), no plainto_tsquery(), en este caso porque ( citando el manual ):

    ... plainto_tsqueryno reconocerá tsqueryoperadores, etiquetas de peso o etiquetas de coincidencia de prefijo en su entrada

  2. Use la 'simple'configuración de búsqueda de texto para generar el, tsqueryya que obviamente desea tomar la palabra 'aprovechar' como está y no aplicar la derivación.

  3. Agregue :*para que sea una búsqueda de prefijo, es decir, encuentre todos los lexemas que comiencen con 'avail'.

Importante: Esta es una búsqueda de prefijo en lexemas (palabras derivadas) en el documento. ¡Una coincidencia de expresión regular sin comodines ( content ~* 'avail') no es exactamente la misma! Este último no está anclado a la izquierda (al comienzo de los lexemas) y también encontraría 'FOOavail', etc.

No está claro si desea el comportamiento descrito en su consulta o el equivalente de la expresión regular agregada. Los índices de trigrama ( pg_trgm) como @Evan ya sugeridos son la herramienta adecuada para eso. Hay muchas preguntas relacionadas sobre dba.SE, intente una búsqueda .

Visión general:

Manifestación

SELECT *
FROM (
   VALUES
     ('Zend has no framework')
   , ('Zend Framework')
   ) sub(t), to_tsvector(t) AS tsv
WHERE tsv @@ to_tsquery('zend <-> fram:*');
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1

Respuesta relacionada reciente (capítulo Enfoque diferente para optimizar la búsqueda ):

Correos electrónicos?

Como mencionó los correos electrónicos, tenga en cuenta que el analizador de búsqueda de texto identifica los correos electrónicos y no los divide en palabras / lexemas separados. Considerar:

SELECT ts_debug('english', 'xangr@some.domain.com')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})

Reemplazaría los separadores @y .en sus correos electrónicos con espacio ( ' ') para indexar palabras contenidas.

Además, dado que está tratando con nombres en correos electrónicos, no con palabras en inglés (o algún otro idioma) , usaría la 'simple'configuración de búsqueda de texto para deshabilitar las funciones de idiomas y otros idiomas :

Construya la ts_vectorcolumna con:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;

Estoy borrando mi respuesta para esto porque de cualquier manera porque estoy claramente equivocado por primera vez y prefiero que no me lo recuerden. Tengo dos preguntas para usted: 1) dónde está :*documentado, y 2) ¿no debería mencionarse que la construcción to_tsvector('simple'..)viene de la mano con instrucciones de que las consultas futuras de ese tsv requerirán también la configuración 'simple' para tsquery? Creo que debería aclarar las ramificaciones de la desactivación derivada de un tsvector / tsquery.
Evan Carroll

@EvanCarroll: no se requiere el uso de la configuración 'simple' . Simplemente evita la inmovilización (como 'ratas' a 'rata') que puede ser o no deseable. No es deseable para el ejemplo dado. Manual: He agregado enlaces arriba ...
Erwin Brandstetter

44
@EvanCarroll: Aparte: pensar que te equivocas la primera vez, sería la segunda. Y eso estaría mal, recursivamente. ;)
Erwin Brandstetter

2
@ErwinBrandstetter, Wow, tu camino me dio una búsqueda a toda velocidad. Antes de su camino, tomó 0.380mspara obtener resultados. Después de su camino tomó 0.079 ms.
xangr

1
@xangr: No, FTS solo ofrece coincidencia de prefijos para lexemas. Para cualquier cosa más, mira pg_trgm. FTS es más rápido (con un índice más pequeño). Incluso puedes combinar ambos índices ...
Erwin Brandstetter
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.