Valkey: Suche und JSON

JSON-Dokumente mit dem Valkey Search-Modul speichern und abfragen

👋 Willkommen in der Stackhero-Dokumentation!

Stackhero bietet eine einsatzbereite Valkey Cloud-Lösung mit zahlreichen Vorteilen, darunter:

  • Valkey Admin Web-Oberfläche inklusive.
  • Unbegrenzte Nachrichten­größe und Übertragungen.
  • Updates ganz einfach per Klick.
  • Optimale Performance und starke Sicherheit durch eine private, dedizierte Infrastruktur.

Sparen Sie Zeit und vereinfachen Sie Ihren Alltag: Es dauert nur 5 Minuten, um die Valkey Cloud Hosting-Lösung von Stackhero auszuprobieren!

Ihre Valkey-Instanz auf Stackhero enthält essenzielle Module, die vom Valkey-Projekt gepflegt werden. Diese Module machen Valkey zu weit mehr als nur einem Cache: Sie können native JSON-Dokumente speichern, Ihre Daten indexieren und Tag-, numerische, Text- sowie Vektor-Abfragen durchführen – und das alles, ohne eine separate Datenbank verwalten zu müssen.

Drei Module stehen zur Verfügung, alle sind in Ihrem Tarif enthalten und unterliegen derselben permissiven BSD 3-Clause-Lizenz wie Valkey:

  • JSON (JSON.*-Befehle): Speichern und aktualisieren Sie strukturierte JSON-Dokumente mit Unterstützung für JSONPath. Sie können einzelne Felder direkt lesen oder ändern, sodass Sie für kleine Änderungen nie das gesamte Dokument neu schreiben müssen.
  • Search (FT.*-Befehle): Führen Sie sekundäre Indizierung, Tag-, numerische und Volltextabfragen sowie Vektorsuche durch.
  • Bloom (BF.*-Befehle): Nutzen Sie Bloom-Filter, um effizient die Frage „Habe ich das schon gesehen?“ über große Datensätze hinweg mit minimalem Speicherbedarf zu beantworten.

Module sind standardmäßig deaktiviert, sodass Ihr bestehender Service sein aktuelles Verhalten beibehält, bis Sie sie aktivieren.

  1. Öffnen Sie Ihren Service im Stackhero Dashboard.
  2. Gehen Sie zur Service-Konfiguration.
  3. Wählen Sie im Abschnitt Module die Module aus, die Sie aktivieren möchten.
  4. Speichern Sie Ihre Änderungen.

Valkey wird neu gestartet, um die ausgewählten Module zu laden. Dies dauert in der Regel nur wenige Sekunden.

Wenn Sie Daten mit einem Modul gespeichert haben (z. B. ein JSON-Dokument oder einen Bloom-Filter), lassen Sie dieses Modul aktiviert. Valkey kann diese Daten ohne das Modul, das sie erstellt hat, nicht lesen. Das Deaktivieren des Moduls würde verhindern, dass Ihr Service erfolgreich neu startet.

Sie können jederzeit prüfen, welche Module aktuell geladen sind:

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

Sie können strukturierte Dokumente nativ als JSON speichern, ohne sie in Strings zu serialisieren:

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

Das Lesen oder Aktualisieren eines einzelnen Feldes ist schnell, atomar und wird serverseitig ausgeführt:

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

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

Mit diesem Ansatz entfällt die Notwendigkeit, bei jeder Änderung das gesamte Dokument in Ihrer Anwendung abzurufen und zu parsen. Beispielsweise ist das Dekrementieren eines Lagerbestandszählers jetzt eine einzige atomare Operation. Es gibt keine Race Conditions oder zusätzlichen Code mehr.

Der Befehlssatz JSON.* entspricht der API von RedisJSON, sodass die meisten Valkey- und Redis-Clients ohne Anpassungen funktionieren.

Erstellen Sie einen Index einmalig, und Valkey hält ihn für jeden Schlüssel, der Ihrem Präfix entspricht, aktuell – auch für Schlüssel, die vor der Indexerstellung geschrieben wurden:

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

Sie können Ihre indexierten Daten mit ausdrucksstarken Suchbefehlen abfragen:

# Exakte Tag-Übereinstimmung
FT.SEARCH productsIndex "@brand:{Bianca}"

# Numerischer Bereich
FT.SEARCH productsIndex "@price:[0 500]"

# Kombinierte Abfrage
FT.SEARCH productsIndex "@brand:{Bianca} @price:[0 500]"

# Volltextsuche nach Name
FT.SEARCH productsIndex "espresso"

Sie können auf demselben Index auch Aggregationen mit FT.AGGREGATE durchführen. Mit dem Befehl FT.INFO können Sie den Status des Index prüfen, einschließlich des Fortschritts von Hintergrund-Indexierungsjobs.

Auch JSON-Dokumente sind indizierbar. Wenn das JSON-Modul aktiviert ist, können Sie ON JSON und JSONPath-Ausdrücke in Ihrem Schema verwenden.

Da Valkey dasselbe Protokoll wie Redis verwendet, ist jeder Redis-Client kompatibel. Sie können dieses Beispiel mit dem offiziellen node-redis Client nutzen:

import { createClient, SCHEMA_FIELD_TYPE } from 'redis';

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

// Erstellen Sie den Index einmalig beim Start
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();

Sie können den redis-py Client nutzen, um mit den Suchfunktionen von Valkey zu arbeiten:

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)

# Erstellen Sie den Index einmalig beim Start
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)
  • Das Search-Modul bietet einen fokussierten Befehlssatz: FT.CREATE, FT.SEARCH, FT.AGGREGATE, FT.INFO, FT.DROPINDEX und FT._LIST. Diese decken Tag-, numerische, Text- und Vektor-Abfragen effizient ab. Falls Ihre Anwendung erweiterte Volltextfunktionen benötigt (wie Rechtschreibprüfung, Synonyme oder Vorschlagswörterbücher), bietet die Redis Query Engine weitergehende Möglichkeiten.
  • Indizes sind pro Datenbank und funktionieren in jeder Datenbank. Ein Index, der beispielsweise in Datenbank 3 erstellt wurde, ist nur von Datenbank 3 aus sichtbar und abfragbar. Hier erweitert Valkey die Möglichkeiten gegenüber der Redis-Datenbankauswahl, die Indizierung nur auf Datenbank 0 unterstützt.
  • Indizes nutzen den Arbeitsspeicher Ihres Tarifs, genau wie Ihre Daten. Sie können used_memory in Ihren Prometheus-Metriken nach dem Aufbau eines Index überwachen.
  • Die Indizierung bestehender Schlüssel läuft im Hintergrund. Direkt nach Ausführung von FT.CREATE können Suchergebnisse für einige Sekunden unvollständig sein, während der Index aufgebaut wird.
  • Alle Modulbefehle sind aktiviert. Jeder Befehl aus jedem Modul steht in Ihrem Service ohne Einschränkungen zur Verfügung.

Wenn Sie Vektorsuche, semantische Suche oder Retrieval-Augmented Generation erkunden möchten, lesen Sie den Leitfaden zur Vektorsuche.