Valkey: Recherche et JSON

Stocker et interroger des documents JSON avec le module de recherche Valkey

👋 Bienvenue dans la documentation Stackhero !

Stackhero propose une solution Valkey cloud clé en main qui offre de nombreux avantages, dont :

  • Interface web Valkey Admin incluse.
  • Taille et transferts de messages illimités.
  • Mises à jour faciles en un seul clic.
  • Performance optimale et sécurité avancée grâce à une infrastructure privée et dédiée.

Gagnez du temps et simplifiez-vous la vie : il ne vous faut que 5 minutes pour essayer l’hébergement Valkey cloud de Stackhero !

Votre instance Valkey sur Stackhero inclut des modules essentiels maintenus par le projet Valkey. Ces modules font de Valkey bien plus qu’un simple cache : vous pouvez stocker des documents JSON natifs, indexer vos données et effectuer des requêtes par tag, numériques, textuelles et vectorielles, le tout sans avoir à gérer une base de données distincte.

Trois modules sont disponibles, tous inclus dans votre forfait et sous la même licence BSD 3-Clause permissive que Valkey :

  • JSON (commandes JSON.*) : Stockez et mettez à jour des documents JSON structurés avec la prise en charge de JSONPath. Vous pouvez lire ou modifier directement des champs individuels, sans jamais avoir à réécrire le document complet pour de petits changements.
  • Search (commandes FT.*) : Effectuez de l’indexation secondaire, des requêtes par tag, numériques, en texte intégral, ainsi que des recherches par similarité vectorielle.
  • Bloom (commandes BF.*) : Utilisez des filtres Bloom pour répondre efficacement à la question « ai-je déjà vu ceci ? » sur de grands ensembles de données, tout en utilisant très peu de mémoire.

Les modules sont désactivés par défaut, donc votre service conserve son comportement actuel tant que vous ne les activez pas.

  1. Ouvrez votre service sur le dashboard Stackhero.
  2. Accédez à la configuration du service.
  3. Dans la section Modules, sélectionnez les modules que vous souhaitez activer.
  4. Enregistrez vos modifications.

Valkey redémarre pour charger les modules sélectionnés. Cela prend généralement seulement quelques secondes.

Si vous avez stocké des données à l’aide d’un module (comme un document JSON ou un filtre Bloom), gardez ce module activé. Valkey ne peut pas lire ces données sans le module qui les a créées. Désactiver le module empêcherait le redémarrage réussi de votre service.

Vous pouvez vérifier à tout moment quels modules sont actuellement chargés :

valkey-cli -u "rediss://default:<yourPassword>@<XXXXXX>.stackhero-network.com:<PORT_TLS>" MODULE LIST

Vous pouvez stocker des documents structurés nativement au format JSON, sans avoir à les sérialiser en chaînes de caractères :

JSON.SET product:1 $ '{"name":"Espresso machine","brand":"Bianca","price":459,"stock":12}'

Lire ou mettre à jour un champ unique est rapide, atomique et géré côté serveur :

JSON.GET product:1 $.price
# "[459]"

JSON.NUMINCRBY product:1 $.stock -1
# "[11]"

Cette approche élimine le besoin de récupérer et d’analyser tout le document dans votre application à chaque modification. Par exemple, décrémenter un compteur de stock devient une opération atomique unique. Plus de conditions de concurrence ni de code supplémentaire.

L’ensemble de commandes JSON.* correspond à l’API de RedisJSON, donc la plupart des clients Valkey et Redis fonctionnent sans modification.

Créez un index une seule fois, et Valkey le maintient à jour pour chaque clé correspondant à votre préfixe, même pour les clés écrites avant la création de l’index :

FT.CREATE productsIndex
  ON HASH
  PREFIX 1 product:
  SCHEMA
    name TEXT
    brand TAG
    price NUMERIC

Vous pouvez interroger vos données indexées avec des commandes de recherche expressives :

# Correspondance exacte sur un tag
FT.SEARCH productsIndex "@brand:{Bianca}"

# Plage numérique
FT.SEARCH productsIndex "@price:[0 500]"

# Requête combinée
FT.SEARCH productsIndex "@brand:{Bianca} @price:[0 500]"

# Recherche en texte intégral sur le nom
FT.SEARCH productsIndex "espresso"

Vous pouvez aussi effectuer des agrégations sur le même index avec FT.AGGREGATE. La commande FT.INFO vous permet de vérifier l’état de l’index, y compris la progression des tâches d’indexation en arrière-plan.

Les documents JSON sont également indexables. Lorsque le module JSON est activé, vous pouvez utiliser ON JSON et des expressions JSONPath dans votre schéma.

Puisque Valkey utilise le même protocole que Redis, tout client Redis est compatible. Vous pouvez utiliser cet exemple avec le client node-redis officiel :

import { createClient, SCHEMA_FIELD_TYPE } from 'redis';

const client = createClient({ url: process.env.STACKHERO_VALKEY_URL_TLS });
await client.connect();

// Créez l’index une seule fois au démarrage
try {
  await client.ft.create(
    'productsIndex',
    {
      name: SCHEMA_FIELD_TYPE.TEXT,
      brand: SCHEMA_FIELD_TYPE.TAG,
      price: SCHEMA_FIELD_TYPE.NUMERIC
    },
    { ON: 'HASH', PREFIX: 'product:' }
  );
} catch (error) {
  if (!error.message.includes('Index already exists')) {
    throw error;
  }
}

await client.hSet('product:1', { name: 'Espresso machine', brand: 'Bianca', price: '459' });

const results = await client.ft.search('productsIndex', '@brand:{Bianca} @price:[0 500]');
console.log(results.total, results.documents);

await client.quit();

Vous pouvez utiliser le client redis-py pour exploiter les fonctionnalités de recherche de Valkey :

import os
import redis
from redis.commands.search.field import TextField, TagField, NumericField
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query

r = redis.from_url(os.environ['STACKHERO_VALKEY_URL_TLS'], decode_responses=True)

# Créez l’index une seule fois au démarrage
try:
    r.ft('productsIndex').create_index(
        (TextField('name'), TagField('brand'), NumericField('price')),
        definition=IndexDefinition(prefix=['product:'], index_type=IndexType.HASH),
    )
except redis.ResponseError as error:
    if 'Index already exists' not in str(error):
        raise

r.hset('product:1', mapping={'name': 'Espresso machine', 'brand': 'Bianca', 'price': 459})

results = r.ft('productsIndex').search(Query('@brand:{Bianca} @price:[0 500]'))
print(results.total, results.docs)
  • Le module de recherche propose un ensemble de commandes ciblé : FT.CREATE, FT.SEARCH, FT.AGGREGATE, FT.INFO, FT.DROPINDEX et FT._LIST. Ces commandes couvrent efficacement les requêtes par tag, numériques, textuelles et vectorielles. Si votre application nécessite des fonctionnalités avancées de recherche en texte intégral (comme la correction orthographique, les synonymes ou les suggestions), le moteur de requête Redis offre davantage de possibilités.
  • Les index sont propres à chaque base de données et fonctionnent dans chaque base. Par exemple, un index créé dans la base 3 n’est visible et interrogeable que depuis la base 3. C’est une capacité où Valkey va au-delà de la sélection de base Redis, qui ne prend en charge l’indexation que sur la base 0.
  • Les index utilisent la mémoire de votre forfait, tout comme vos données. Vous pouvez surveiller used_memory dans vos métriques Prometheus après la création d’un index.
  • L’indexation des clés existantes s’effectue en arrière-plan. Juste après l’exécution de FT.CREATE, les résultats de recherche peuvent être incomplets pendant quelques secondes, le temps que l’index soit construit.
  • Toutes les commandes des modules sont activées. Chaque commande de chaque module est disponible sur votre service, sans aucune restriction.

Si vous souhaitez explorer la recherche vectorielle, la recherche sémantique ou le retrieval-augmented generation, consultez le guide sur la recherche vectorielle.