Redis®*: Recherche et JSON

Stockez des documents JSON et interrogez-les efficacement avec le moteur de requêtes Redis

👋 Bienvenue sur la documentation de Stackhero !

Stackhero propose une solution Redis cloud prête à l'emploi qui offre de nombreux avantages, notamment :

  • Interface web Redis Commander incluse.
  • Taille et transferts de messages illimités.
  • Mises à jour simplifiées en un clic.
  • Performance optimale et sécurité renforcée grâce à une infrastructure privée et dédiée.

Gagnez du temps et simplifiez-vous la vie : il suffit de 5 minutes pour essayer la solution d'hébergement Redis cloud de Stackhero !

Votre instance Redis sur Stackhero inclut tous les modules disponibles dans Redis Open Source. Ces modules font de Redis bien plus qu'un simple cache : vous pouvez stocker de véritables documents JSON, les indexer et effectuer des recherches full-text, numériques et par tags directement. Il n'est pas nécessaire d'ajouter une autre base de données à votre stack.

Les quatre modules suivants sont inclus dans votre offre :

  • JSON (commandes JSON.*) : Ajoute un type JSON natif avec prise en charge de JSONPath. Vous pouvez lire ou mettre à jour des champs individuels sans réécrire l'ensemble du document.
  • Search (commandes FT.*), également appelé moteur de requêtes Redis : Offre la recherche full-text, l'indexation secondaire, les agrégations et la recherche vectorielle.
  • Bloom (commandes BF.*, CF.*, CMS.*, TOPK.*, TDIGEST.*) : Structures de données probabilistes permettant de répondre efficacement à des questions comme "ai-je déjà vu ceci ?" sur de grands ensembles, tout en utilisant très peu de mémoire.
  • Time series (commandes TS.*) : Propose un type time series avec rétention, downsampling et fonctions d'agrégation.

Les vector sets (VADD, VSIM) sont intégrés directement dans Redis. Ils permettent une recherche vectorielle efficace pour les embeddings et sont toujours disponibles sur votre service. Aucune configuration n'est nécessaire.

Les modules sont désactivés par défaut. Cela garantit que les services existants conservent leur comportement initial jusqu'à ce que vous choisissiez d'activer de nouvelles fonctionnalités.

  1. Ouvrez votre service dans le tableau de bord Stackhero.
  2. Accédez à la configuration du service.
  3. Dans la section Modules, sélectionnez les modules souhaités.
  4. Enregistrez vos modifications.

Votre service Redis redémarrera avec les modules sélectionnés chargés. Cette opération prend généralement quelques secondes.

Dès que vous stockez des données avec un module (par exemple un document JSON, un filtre Bloom ou une time series), gardez ce module activé. Redis ne peut pas accéder aux données créées par un module désactivé, et sa désactivation empêchera le démarrage de votre service. Les vector sets sont toujours disponibles, car ils font partie intégrante de Redis.

Pour vérifier les modules actuellement chargés, vous pouvez exécuter :

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

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

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

Cette méthode vous permet de lire ou de mettre à jour des champs individuels de façon atomique et côté serveur :

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

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

JSON.ARRAPPEND product:1 $.tags '"gift"'

Ce workflow simplifie vos développements et limite les erreurs. Par exemple, décrémenter un compteur de stock ne nécessite pas de lire, parser et réécrire tout le document dans votre application. L'opération est effectuée de façon sûre et immédiate côté serveur.

Vous trouverez la liste complète des commandes dans la documentation Redis JSON.

Vous n'avez besoin de déclarer un index qu'une seule fois. Redis le maintient automatiquement à jour pour chaque clé correspondant au préfixe choisi, y compris pour les clés existantes avant la création de l'index.

FT.CREATE productsIndex
  ON JSON
  PREFIX 1 product:
  SCHEMA
    $.name AS name TEXT
    $.brand AS brand TAG
    $.price AS price NUMERIC SORTABLE
    $.tags[*] AS tags TAG

Vous pouvez ensuite exécuter des requêtes comme :

# Recherche full-text sur le nom, avec une plage de prix
FT.SEARCH productsIndex "@name:(espresso) @price:[0 500]"

# Recherche exacte sur la marque, triée par prix
FT.SEARCH productsIndex "@brand:{Bianca}" SORTBY price ASC

# Recherche par préfixe pour l'autocomplétion
FT.SEARCH productsIndex "@name:(espr*)"

Redis peut également effectuer des agrégations directement sur l'index, ce qui permet de répondre à des requêtes analytiques sans exporter les données :

FT.AGGREGATE productsIndex "*"
  GROUPBY 1 @brand
  REDUCE COUNT 0 AS products
  REDUCE AVG 1 @price AS averagePrice
  SORTBY 2 @products DESC

Si vous stockez vos données dans des hashes simples au lieu de JSON, vous pouvez utiliser ON HASH et des noms de champs standards dans votre schéma.

import { createClient, SCHEMA_FIELD_TYPE } from 'redis';

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

// Création de l'index au démarrage
try {
  await client.ft.create(
    'productsIndex',
    {
      '$.name': { type: SCHEMA_FIELD_TYPE.TEXT, AS: 'name' },
      '$.brand': { type: SCHEMA_FIELD_TYPE.TAG, AS: 'brand' },
      '$.price': { type: SCHEMA_FIELD_TYPE.NUMERIC, AS: 'price', SORTABLE: true }
    },
    { ON: 'JSON', PREFIX: 'product:' }
  );
}
catch (error) {
  if (!error.message.includes('Index already exists')) {
    throw error;
  }
}

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

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

await client.quit();
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_REDIS_URL_TLS'], decode_responses=True)

# Création de l'index au démarrage
try:
    r.ft('productsIndex').create_index(
        (
            TextField('$.name', as_name='name'),
            TagField('$.brand', as_name='brand'),
            NumericField('$.price', as_name='price', sortable=True),
        ),
        definition=IndexDefinition(prefix=['product:'], index_type=IndexType.JSON),
    )
except redis.ResponseError as error:
    if 'Index already exists' not in str(error):
        raise

r.json().set('product:1', '$', {
    'name': 'Espresso machine',
    'brand': 'Bianca',
    'price': 459,
})

results = r.ft('productsIndex').search(Query('@name:(espresso) @price:[0 500]'))
print(results.total, results.docs)
  • Les indexes Search ne fonctionnent que sur la base de données 0. FT.CREATE retourne une erreur sur toute autre base. Si votre application utilise plusieurs bases logiques, gardez les données indexables sur la base 0, ou utilisez des préfixes de clés pour séparer les ensembles de données.
  • Les indexes utilisent la mémoire de votre offre, comme vos données. Les indexes textuels ou vectoriels volumineux peuvent représenter une part importante, vous pouvez surveiller used_memory dans vos métriques Prometheus après leur création.
  • La création d'un index sur des clés existantes s'effectue en arrière-plan. Juste après un FT.CREATE, les recherches peuvent temporairement retourner des résultats incomplets. Vous pouvez suivre la progression de l'indexation avec FT.INFO productsIndex.
  • Toutes les commandes des modules sont pleinement disponibles. Chaque commande de chaque module activé est prête à l'emploi sur votre service.

Pour en savoir plus sur la similarité vectorielle, la recherche sémantique ou le retrieval-augmented generation, consultez le guide sur la recherche vectorielle.