FT.SEARCH

FT.SEARCH busca en el índice con la consulta proporcionada y devuelve los valores especificados.

Para obtener información detallada sobre la sintaxis de las consultas, consulta Sintaxis de consulta.

Sintaxis

FT.SEARCH index query
  [NOCONTENT]
  [TIMEOUT timeout]
  [PARAMS nargs name value [ name value ...]]
  [RETURN num field [AS alias] [ field [AS alias] ... ]]
  [LIMIT offset num]
  DIALECT 2
  • index (obligatorio): el índice que quieres consultar.
  • query (obligatorio): es tu consulta. Para obtener información detallada sobre la sintaxis de las consultas, consulta Sintaxis de consulta.
  • NOCONTENT (opcional): devuelve solo los IDs de los documentos y excluye el contenido.
  • TIMEOUT (opcional): te permite definir un valor de tiempo de espera para el comando de búsqueda.
  • PARAMS (opcional): el número de pares clave-valor multiplicado por dos.
  • RETURN (opcional): especifica los campos que quieres recuperar de tus documentos, junto con los alias de los valores devueltos. De forma predeterminada, se devuelven todos los campos, a menos que se defina la opción NOCONTENT, en cuyo caso no se devuelve ningún campo. Si num es 0, se comporta igual que NOCONTENT.
  • LIMIT (opcional): te permite elegir la paginación con un desplazamiento y un recuento de números. Si no usas este parámetro, el valor predeterminado es LIMIT 0 10, que devuelve un máximo de 10 claves.
  • DIALECT 2 (opcional): especifica tu dialecto. Solo se admite el dialecto 2.

Devolución de comandos

  • Este comando devuelve una matriz o un mensaje de error. Los elementos de la matriz devuelta representan los resultados que mejor coinciden con la consulta. Cada elemento de la matriz tiene lo siguiente:

  • La clave hash de entrada

  • Una matriz de lo siguiente:

    • Valor clave: [$score_as ] score_value
    • Valor de distancia
    • Nombre de atributo
    • Valor del vector

    Si se usa NOCONTENT, los elementos de la matriz solo constan de los IDs de documento.

Ejemplo 1: Consulta de búsqueda vectorial simple

En este ejemplo, vamos a suponer que estamos creando un índice de búsqueda de propiedades en el que los clientes pueden buscar propiedades en función de algunas características. Supongamos que tenemos una lista de propiedades con los siguientes atributos:

  • Descripción: incrustación de vector de la propiedad dada.
  • Otros campos: cada propiedad también puede tener otros metadatos. Sin embargo, para simplificar, en este ejemplo se ignoran otros campos.

Primero, creamos un índice HNSW con la descripción como campo vectorial mediante el comando FT.CREATE:

FT.CREATE idx SCHEMA description VECTOR HNSW 6 TYPE FLOAT32 DIM 3 DISTANCE_METRIC L2

Ahora podemos insertar algunas propiedades (también se puede hacer antes de crear el índice) con el comando HSET:

HSET p1 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
HSET p2 description "\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00"
HSET p3 description "\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00"
HSET p4 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
HSET p5 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"

Ahora podemos realizar consultas con el comando FT.SEARCH. La siguiente consulta devuelve hasta cinco de las propiedades más similares al vector de consulta proporcionado:

FT.SEARCH idx "*=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2

Resultado devuelto:

 1) (integer) 5
 2) p5
 3) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
 4) p4
 5) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
 6) p2
 7) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00
 8) p1
 9) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
10) p3
11) 1) __description_score
    2) 0.0399999953806
    3) description
    4) \x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00

Código de ejemplo

Python

# Before running, ensure you have installed redis-py:
#    pip install redis

import redis
client = redis.Redis(host='your_server_host', port=6379)
result = client.execute_command('FT.SEARCH', 'idx', '*=>[KNN 5 @description $query_vector]', 'PARAMS', '2', 'query_vector', '"\xcd\xccL?\x00\x00\x00\x00"', 'DIALECT', '2')
print(result)

NodeJS

# Before running, ensure you have installed ioredis:
#   npm install ioredis

const Redis = require("ioredis");
const redis = new Redis(6379, "your_server_host")
redis.call("FT.SEARCH", "idx", "*=>[KNN 5 @description $query_vector]", "PARAMS", "2", "query_vector", "\xcd\xccL?\x00\x00\x00\x00\x00\x00", "DIALECT", "2").then(result => {
console.log(result);
redis.disconnect();
});

CLI

# Before running, ensure you have install redis-cli

redis-cli -h your_server_host -p 6379 FT.SEARCH idx "(*)=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2

Ejemplo 2: Búsqueda vectorial con consultas híbridas

En este ejemplo, vamos a hacer una consulta híbrida usando dos atributos adicionales llamados "city" y "price":

  • Descripción: incrustación de vector de la propiedad dada.
  • Ciudad: nombre de la ciudad.
  • Precio: coste de la propiedad.

Primero, creamos un índice con la descripción como campo vectorial, la ciudad como campo de etiqueta y el precio como campo numérico:

FT.CREATE idx SCHEMA description VECTOR HNSW 6 TYPE FLOAT32 DIM 3 DISTANCE_METRIC L2 city TAG price NUMERIC

Ahora podemos insertar algunas propiedades (también se puede hacer antes de crear el índice):

HSET p1 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?" city "NEW YORK" price 500000
HSET p2 description "\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00" city "NEW JERSEY" price 400000
HSET p3 description "\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00" city "BANGALORE" price 60000
HSET p4 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?" city "NEW YORK" price 600000
HSET p5 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?" city "BANGALORE" price 75000

Ahora podemos hacer consultas. La siguiente consulta devuelve hasta cinco de las propiedades más similares al vector de consulta proporcionado, filtrando solo las de Bangalore con un precio inferior a 100.000:

FT.SEARCH idx "(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2

Resultado devuelto:

1) (integer) 2
2) p5
3) 1) __description_score
   2) 1.6400001049
   3) city
   4) BANGALORE
   5) price
   6) 75000
   7) description
   8) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
4) p3
5) 1) __description_score
   2) 0.0399999953806
   3) city
   4) BANGALORE
   5) price
   6) 60000
   7) description
   8) \x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00

Consulta Sintaxis de las consultas para obtener información sobre el formato de las consultas de filtro.

Código de ejemplo

Python

# Before running, ensure you have installed redis-py:
#   pip install redis

import redis
client = redis.Redis(host='your_server_host', port=6379)
result = client.execute_command('FT.SEARCH', 'idx', '(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]', 'PARAMS', '2', 'query_vector', '"\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00"', 'DIALECT', '2')
print(result)

NodeJS

# Before running, ensure you have installed ioredis:
#   npm install ioredis

const Redis = require("ioredis");
const redis = new Redis(6379, "your_server_host")
redis.call("FT.SEARCH", "idx", "(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]", "PARAMS", "2", "query_vector", "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00", "DIALECT", "2").then(result => {
console.log(result);
redis.disconnect();
});

CLI

# Before running, ensure you have install redis-cli

redis-cli -h your_server_host -p 6379 FT.SEARCH idx "(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2