JSON-Feld-Übersicht

Bei der Entwicklung von Anwendungen wie Produktkatalogen, Content-Management-Systemen oder Engines für Benutzerpräferenzen müssen Sie neben den Vektoreinbettungen häufig auch flexible Metadaten speichern. Produktattribute variieren je nach Kategorie, Benutzerpräferenzen entwickeln sich im Laufe der Zeit, und Dokumenteigenschaften haben komplexe verschachtelte Strukturen. JSON-Felder in Milvus lösen diese Herausforderung, indem sie es Ihnen ermöglichen, flexible strukturierte Daten ohne Leistungseinbußen zu speichern und abzufragen.

Was ist ein JSON-Feld?

Ein JSON-Feld ist ein schema-definierter Datentyp (DataType.JSON) in Milvus, der strukturierte Schlüssel-Wert-Daten speichert. Im Gegensatz zu herkömmlichen starren Datenbankspalten können JSON-Felder verschachtelte Objekte, Arrays und gemischte Datentypen aufnehmen und bieten gleichzeitig mehrere Indizierungsoptionen für schnelle Abfragen.

Beispiel einer JSON-Feldstruktur:

{
  "metadata": { 
    "category": "electronics",
    "brand": "BrandA",
    "in_stock": true,
    "price": 99.99,
    "string_price": "99.99",
    "tags": ["clearance", "summer_sale"],
    "supplier": {
      "name": "SupplierX",
      "country": "USA",
      "contact": {
        "email": "support@supplierx.com",
        "phone": "+1-800-555-0199"
      }
    }
  }
}

In diesem Beispiel ist metadata ein einzelnes JSON-Feld, das eine Mischung aus flachen Werten (z. B. category, in_stock), Arrays (tags) und verschachtelten Objekten (supplier) enthält.

Benennungskonvention: Verwenden Sie in JSON-Schlüsseln nur Buchstaben, Zahlen und Unterstriche. Vermeiden Sie Sonderzeichen, Leerzeichen oder Punkte, da diese in Abfragen zu Problemen beim Parsen führen können.

JSON-Feld vs. dynamisches Feld

Ein häufiger Punkt der Verwirrung ist der Unterschied zwischen einem JSON-Feld und einem dynamischen Feld. Obwohl beide mit JSON verwandt sind, dienen sie unterschiedlichen Zwecken.

In der nachstehenden Tabelle sind die wichtigsten Unterschiede zwischen einem JSON-Feld und einem dynamischen Feld zusammengefasst:

Merkmal

JSON-Feld

Dynamisches Feld

Schema-Definition

Ein skalares Feld, das explizit im Auflistungsschema mit dem Typ DataType.JSON deklariert werden muss.

Ein verstecktes JSON-Feld (mit dem Namen $meta), das nicht deklarierte Felder automatisch speichert.

Anwendungsfall

Speichert strukturierte Daten, deren Schema bekannt und konsistent ist.

Speichert flexible, sich entwickelnde oder halb-strukturierte Daten, die nicht in ein festes Schema passen.

Steuerung

Sie kontrollieren den Feldnamen und die Struktur.

Systemgesteuert für undefinierte Felder.

Abfragen

Abfrage über Ihren Feldnamen oder Zielschlüssel innerhalb des JSON-Feldes: metadata["key"].

Direkte Abfrage über den dynamischen Feldschlüssel: "dynamic_key" oder über $meta: $meta["dynamic_key"]

Grundlegende Operationen

Der grundlegende Arbeitsablauf für die Verwendung eines JSON-Feldes besteht darin, es in Ihrem Schema zu definieren, Daten einzufügen und dann die Daten mit spezifischen Filterausdrücken abzufragen.

Definieren eines JSON-Feldes

Um ein JSON-Feld zu verwenden, definieren Sie es explizit in Ihrem Sammlungsschema, wenn Sie die Sammlung erstellen. Das folgende Beispiel zeigt, wie Sie eine Sammlung mit einem metadata -Feld des Typs DataType.JSON erstellen:

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530") # Replace with your server address 

# Create schema
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)

schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True) # Primary field
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5) # Vector field
# Define a JSON field that allows null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)

client.create_collection(
    collection_name="product_catalog",
    schema=schema
)

In diesem Beispiel lässt das im Auflistungsschema definierte JSON-Feld mit nullable=True Nullwerte zu. Einzelheiten finden Sie unter Nullable & Default.

Daten einfügen

Sobald die Sammlung erstellt ist, fügen Sie Entitäten, die strukturierte JSON-Objekte enthalten, in das von Ihnen festgelegte JSON-Feld ein. Ihre Daten sollten als eine Liste von Wörterbüchern formatiert sein.

entities = [
    {
        "product_id": 1,
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
        "metadata": { # JSON field
            "category": "electronics",
            "brand": "BrandA",
            "in_stock": True,
            "price": 99.99,
            "string_price": "99.99",
            "tags": ["clearance", "summer_sale"],
            "supplier": {
                "name": "SupplierX",
                "country": "USA",
                "contact": {
                    "email": "support@supplierx.com",
                    "phone": "+1-800-555-0199"
                }
            }
        }
    }
]

client.insert(collection_name="product_catalog", data=entities)

Filtern von Operationen

Bevor Sie Filteroperationen auf JSON-Feldern durchführen können, müssen Sie sicherstellen:

  • Sie haben einen Index für jedes Vektorfeld erstellt.

  • Die Sammlung ist in den Speicher geladen.

Code anzeigen

index_params = client.prepare_index_params()
index_params.add_index(
    field_name="vector",
    index_type="AUTOINDEX",
    index_name="vector_index",
    metric_type="COSINE"
)

client.create_index(collection_name="product_catalog", index_params=index_params)

client.load_collection(collection_name="product_catalog")

Sobald diese Voraussetzungen erfüllt sind, können Sie die folgenden Ausdrücke verwenden, um Ihre Sammlung auf der Grundlage der Werte im JSON-Feld zu filtern. Diese Filterausdrücke nutzen die spezifische JSON-Pfadsyntax und spezielle Operatoren.

Filtern mit JSON-Pfadsyntax

Um einen bestimmten Schlüssel abzufragen, verwenden Sie die Klammerschreibweise für den Zugriff auf JSON-Schlüssel: json_field_name["key"]. Für verschachtelte Schlüssel verketten Sie diese: json_field_name["key1"]["key2"].

Um nach Entitäten zu filtern, bei denen der category "electronics" ist:

# Define filter expression
filter = 'metadata["category"] == "electronics"'

client.search(
    collection_name="product_catalog",  # Collection name
    data=[[0.1, 0.2, 0.3, 0.4, 0.5]],               # Query vector (must match collection's vector dim)
    limit=5,                           # Max. number of results to return
    filter=filter,                    # Filter expression
    output_fields=["product_id", "metadata"]   # Fields to include in the search results
)

Um nach Entitäten zu filtern, bei denen der verschachtelte Schlüssel supplier["country"] "USA" ist:

# Define filter expression
filter = 'metadata["supplier"]["country"] == "USA"'

res = client.search(
    collection_name="product_catalog",  # Collection name
    data=[[0.1, 0.2, 0.3, 0.4, 0.5]],               # Query vector (must match collection's vector dim)
    limit=5,                           # Max. number of results to return
    filter=filter,                    # Filter expression
    output_fields=["product_id", "metadata"]   # Fields to include in the search results
)

print(res)

Filtern mit JSON-spezifischen Operatoren

Milvus bietet auch spezielle Operatoren für die Abfrage von Array-Werten auf bestimmte JSON-Feldschlüssel. Zum Beispiel:

  • json_contains(identifier, expr): Prüft, ob ein bestimmtes Element oder Unter-Array innerhalb eines JSON-Arrays existiert

  • json_contains_all(identifier, expr): Stellt sicher, dass alle Elemente des angegebenen JSON-Ausdrucks in dem Feld vorhanden sind

  • json_contains_any(identifier, expr): Filtert Entitäten, bei denen mindestens ein Element des JSON-Ausdrucks im Feld vorhanden ist

Um ein Produkt zu finden, das den Wert "summer_sale" unter dem Schlüssel tags hat:

# Define filter expression
filter = 'json_contains(metadata["tags"], "summer_sale")'

res = client.search(
    collection_name="product_catalog",  # Collection name
    data=[[0.1, 0.2, 0.3, 0.4, 0.5]],               # Query vector (must match collection's vector dim)
    limit=5,                           # Max. number of results to return
    filter=filter,                    # Filter expression
    output_fields=["product_id", "metadata"]   # Fields to include in the search results
)

print(res)

Um ein Produkt zu finden, das mindestens einen der Werte "electronics", "new" oder "clearance" unter dem Schlüssel tags enthält:

# Define filter expression
filter = 'json_contains_any(metadata["tags"], ["electronics", "new", "clearance"])'

res = client.search(
    collection_name="product_catalog",  # Collection name
    data=[[0.1, 0.2, 0.3, 0.4, 0.5]],               # Query vector (must match collection's vector dim)
    limit=5,                           # Max. number of results to return
    filter=filter,                    # Filter expression
    output_fields=["product_id", "metadata"]   # Fields to include in the search results
)

print(res)

Weitere Informationen über JSON-spezifische Operatoren finden Sie unter JSON-Operatoren.

Weiter: JSON-Abfragen beschleunigen

Standardmäßig führen Abfragen auf JSON-Felder ohne Beschleunigung einen vollständigen Scan aller Zeilen durch, was bei großen Datensätzen langsam sein kann. Um JSON-Abfragen zu beschleunigen, bietet Milvus erweiterte Indizierungs- und Speicheroptimierungsfunktionen.

Die folgende Tabelle fasst die Unterschiede und die besten Einsatzszenarien zusammen:

Technik

Am besten für

Arrays Beschleunigung

Hinweise

JSON-Indizierung

Kleiner Satz von Schlüsseln, auf die häufig zugegriffen wird, Arrays auf einen bestimmten Array-Schlüssel

Ja (auf indizierten Array-Schlüssel)

Muss eine Vorauswahl der Schlüssel treffen, Wartung erforderlich, wenn sich das Schema weiterentwickelt

JSON-Zerkleinerung

Allgemeine Beschleunigung über viele Schlüssel hinweg, flexibel für unterschiedliche Abfragen

Nein (beschleunigt nicht die Werte innerhalb von Arrays)

Zusätzliche Speicherkonfiguration, Arrays benötigen weiterhin einen Index pro Schlüssel

NGRAM-Index

Wildcard-Suche, Teilstring-Matching in Textfeldern

K.A.

Nicht für numerische/bereichsbezogene Filter

Tipp: Sie können diese Ansätze kombinieren, z. B. JSON Shredding zur Beschleunigung breiter Abfragen, JSON Indexing für hochfrequente Array-Schlüssel und NGRAM Indexing für eine flexible Textsuche verwenden.

Einzelheiten zur Implementierung finden Sie unter:

FAQ

Gibt es irgendwelche Beschränkungen für die Größe eines JSON-Feldes?

Ja. Jedes JSON-Feld ist auf 65.536 Bytes begrenzt.

Unterstützt ein JSON-Feld die Einstellung eines Standardwertes?

Nein, JSON-Felder unterstützen keine Standardwerte. Sie können jedoch nullable=True festlegen, wenn Sie das Feld definieren, um leere Einträge zuzulassen.

Weitere Informationen finden Sie unter Nullable & Default.

Gibt es Namenskonventionen für JSON-Feldschlüssel?

Ja, um die Kompatibilität mit Abfragen und Indizierungen zu gewährleisten:

  • Verwenden Sie in JSON-Schlüsseln nur Buchstaben, Zahlen und Unterstriche.

  • Vermeiden Sie die Verwendung von Sonderzeichen, Leerzeichen oder Punkten (., /, etc.).

  • Inkompatible Schlüssel können zu Parsing-Problemen in Filterausdrücken führen.

Wie behandelt Milvus Zeichenkettenwerte in JSON-Feldern?

Milvus speichert String-Werte genau so, wie sie in der JSON-Eingabe erscheinen - ohne semantische Umwandlung. Nicht korrekt zitierte Zeichenketten können beim Parsen zu Fehlern führen.

Beispiele für gültige Zeichenketten:

"a\"b", "a'b", "a\\b"

Beispiele für ungültige Strings:

'a"b', 'a\'b'