JSON-Feld
Ein JSON-Feld ist ein Skalarfeld, das zusätzliche Informationen zusammen mit Vektoreinbettungen in Schlüssel-Wert-Paaren speichert. Hier ist ein Beispiel dafür, wie Daten im JSON-Format gespeichert werden:
{
"metadata": {
"product_info": {
"category": "electronics",
"brand": "BrandA"
},
"price": 99.99,
"in_stock": true,
"tags": ["summer_sale", "clearance"]
}
}
Grenzwerte
Feldgröße: JSON-Felder sind auf eine Größe von 65.536 Byte begrenzt.
Verschachtelte Wörterbücher: Alle verschachtelten Dictionaries innerhalb von JSON-Feldwerten werden bei der Speicherung als einfache Zeichenketten behandelt.
Standardwerte: JSON-Felder unterstützen keine Standardwerte. Sie können jedoch das Attribut
nullableaufTruesetzen, um Nullwerte zuzulassen. Einzelheiten finden Sie unter Nullable & Default.Typübereinstimmung: Wenn der Schlüsselwert eines JSON-Feldes ein Integer- oder Float-Wert ist, kann er nur (über Ausdrucksfilter) mit einem anderen numerischen Schlüssel desselben Typs verglichen werden.
Benennung: Es wird empfohlen, bei der Benennung von JSON-Schlüsseln nur Buchstaben, Zahlen und Unterstriche zu verwenden. Die Verwendung anderer Zeichen kann zu Problemen bei der Filterung oder Suche führen.
Behandlung von Zeichenketten: Milvus speichert String-Werte in JSON-Feldern wie eingegeben, ohne semantische Konvertierung. Zum Beispiel:
'a"b'"a'b", und werden genau so gespeichert, wie sie sind.'a\\'b'"a\\"b"'a'b'und"a"b"werden als ungültig betrachtet.
JSON-Indizierung: Bei der Indizierung eines JSON-Feldes können Sie einen oder mehrere Pfade im JSON-Feld angeben, um die Filterung zu beschleunigen. Jeder zusätzliche Pfad erhöht den Indizierungs-Overhead, daher sollten Sie Ihre Indizierungsstrategie sorgfältig planen. Weitere Überlegungen zur Indizierung eines JSON-Feldes finden Sie unter Überlegungen zur JSON-Indizierung.
JSON-Feld hinzufügen
Um dieses JSON-Feld metadata zu Ihrem Auflistungsschema hinzuzufügen, verwenden Sie DataType.JSON. Im folgenden Beispiel wird ein JSON-Feld metadata definiert, das Nullwerte zulässt:
# Import necessary libraries
from pymilvus import MilvusClient, DataType
# Define server address
SERVER_ADDR = "http://localhost:19530"
# Create a MilvusClient instance
client = MilvusClient(uri=SERVER_ADDR)
# Define the collection schema
schema = client.create_schema(
auto_id=False,
enable_dynamic_fields=True,
)
# Add a JSON field that supports null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)
schema.add_field(field_name="pk", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=3)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
schema.addField(AddFieldReq.builder()
.fieldName("metadata")
.dataType(DataType.JSON)
.isNullable(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("pk")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("embedding")
.dataType(DataType.FloatVector)
.dimension(3)
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/index"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
schema := entity.NewSchema()
schema.WithField(entity.NewField().
WithName("pk").
WithDataType(entity.FieldTypeInt64).
WithIsAutoID(true),
).WithField(entity.NewField().
WithName("embedding").
WithDataType(entity.FieldTypeFloatVector).
WithDim(3),
).WithField(entity.NewField().
WithName("metadata").
WithDataType(entity.FieldTypeJSON),
)
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const schema = [
{
name: "metadata",
data_type: DataType.JSON,
},
{
name: "pk",
data_type: DataType.Int64,
is_primary_key: true,
},
{
name: "embedding",
data_type: DataType.FloatVector,
dim: 3,
},
];
export jsonField='{
"fieldName": "metadata",
"dataType": "JSON"
}'
export pkField='{
"fieldName": "pk",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "embedding",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 3
}
}'
export schema="{
\"autoID\": false,
\"enableDynamicField\": true,
\"fields\": [
$jsonField,
$pkField,
$vectorField
]
}"
Setzen Sie
enable_dynamic_fields=True, wenn Sie in Zukunft zusätzliche, nicht definierte Felder einfügen müssen.Verwenden Sie
nullable=True, um fehlende oder ungültige JSON-Objekte zuzulassen.
Index-Parameter setzen
Die Indizierung hilft Milvus, große Datenmengen schnell zu filtern oder zu durchsuchen. In Milvus ist die Indexierung:
Obligatorisch für Vektorfelder (um Ähnlichkeitssuchen effizient durchzuführen).
Optional für JSON-Felder (um skalare Filter auf bestimmten JSON-Pfaden zu beschleunigen).
Indizieren eines JSON-FeldesCompatible with Milvus 2.5.10+
Standardmäßig sind JSON-Felder nicht indiziert, so dass alle Filterabfragen (z. B. metadata["price"] < 100) alle Zeilen durchsuchen müssen. Wenn Sie Abfragen auf bestimmten Pfaden innerhalb des Feldes metadata beschleunigen möchten, können Sie einen invertierten Index auf jedem Pfad erstellen, der Sie interessiert.
In diesem Beispiel werden wir zwei Indizes auf verschiedenen Pfaden innerhalb des JSON-Feldes metadata erstellen:
index_params = client.prepare_index_params()
# Example 1: Index the 'category' key inside 'product_info' as a string
index_params.add_index(
field_name="metadata", # JSON field name to index
index_type="INVERTED", # Index type. Set to INVERTED
index_name="json_index_1", # Index name
params={
"json_path": "metadata[\"product_info\"][\"category\"]", # Path in JSON field to index
"json_cast_type": "varchar" # Data type that the extracted JSON values will be cast to
}
)
# Example 2: Index 'price' as a numeric type (double)
index_params.add_index(
field_name="metadata",
index_type="INVERTED",
index_name="json_index_2",
params={
"json_path": "metadata[\"price\"]",
"json_cast_type": "double"
}
)
import io.milvus.v2.common.IndexParam;
List<IndexParam> indexes = new ArrayList<>();
Map<String,Object> extraParams_1 = new HashMap<>();
extraParams_1.put("json_path", "metadata[\"product_info\"][\"category\"]");
extraParams_1.put("json_cast_type", "varchar");
indexes.add(IndexParam.builder()
.fieldName("metadata")
.indexName("json_index_1")
.indexType(IndexParam.IndexType.INVERTED)
.extraParams(extraParams_1)
.build());
Map<String,Object> extraParams_2 = new HashMap<>();
extraParams_2.put("json_path", "metadata[\"price\"]");
extraParams_2.put("json_cast_type", "double");
indexes.add(IndexParam.builder()
.fieldName("metadata")
.indexName("json_index_2")
.indexType(IndexParam.IndexType.INVERTED)
.extraParams(extraParams_2)
.build());
jsonIndex1 := index.NewJSONPathIndex(index.Inverted, "varchar", `metadata["product_info"]["category"]`)
jsonIndex2 := index.NewJSONPathIndex(index.Inverted, "double", `metadata["price"]`)
indexOpt1 := milvusclient.NewCreateIndexOption("my_collection", "metadata", jsonIndex1)
indexOpt2 := milvusclient.NewCreateIndexOption("my_collection", "metadata", jsonIndex2)
const indexParams = [
{
field_name: "metadata",
index_type: "INVERTED",
index_name: "json_index_1",
params: {
json_path: "metadata[\"product_info\"][\"category\"]",
json_cast_type: "varchar"
}
},
{
field_name: "metadata",
index_type: "INVERTED",
index_name: "json_index_2",
params: {
json_path: "metadata[\"price\"]",
json_cast_type: "double"
}
}
]
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"indexParams": [
{
"fieldName": "metadata",
"indexName": "json_index_1",
"indexType": "INVERTED",
"params": {
"json_path": "metadata[\"product_info\"][\"category\"]",
"json_cast_type": "varchar"
}
}
]
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"indexParams": [
{
"fieldName": "metadata",
"indexName": "json_index_2",
"indexType": "INVERTED",
"params": {
"json_path": "metadata[\"price\"]",
"json_cast_type": "double"
}
}
]
}'
Parameter |
Beschreibung |
Beispiel Wert |
|---|---|---|
|
Name des JSON-Feldes in Ihrem Schema. |
|
|
Zu erstellender Indextyp; derzeit wird nur |
|
|
(Optional) Ein benutzerdefinierter Indexname. Geben Sie verschiedene Namen an, wenn Sie mehrere Indizes für dasselbe JSON-Feld erstellen. |
|
|
Gibt an, welcher JSON-Pfad indiziert werden soll. Sie können auf verschachtelte Schlüssel, Array-Positionen oder beides abzielen (z.B. |
|
|
Datentyp, in den Milvus die extrahierten JSON-Werte umwandelt, wenn der Index erstellt wird. Gültige Werte:
|
|
Überlegungen zur JSON-Indizierung
Logik der Filterung:
Wenn Sie einen Index vom Typ double (
json_cast_type="double") erstellen, können nur Filterbedingungen vom Typ numerisch den Index verwenden. Wenn der Filter einen doppelten Index mit einer nicht-numerischen Bedingung vergleicht, greift Milvus auf die Brute-Force-Suche zurück.Wenn Sie einen Index vom Typ varchar erstellen (
json_cast_type="varchar"), können nur Filterbedingungen vom Typ string den Index verwenden. Andernfalls greift Milvus auf die Brute-Force-Suche zurück.Dieboolesche Indizierung verhält sich ähnlich wie der varchar-Typ.
Term-Ausdrücke:
- Sie können
json["field"] in [value1, value2, …]verwenden. Der Index funktioniert jedoch nur für skalare Werte, die unter diesem Pfad gespeichert sind. Wennjson["field"]ein Array ist, fällt die Abfrage auf Brute-Force zurück (Array-artige Indizierung wird noch nicht unterstützt).
- Sie können
Numerische Genauigkeit:
- Intern indiziert Milvus alle numerischen Felder als Doubles. Wenn ein numerischer Wert 2 übersteigt, verliert er an Präzision, und Abfragen auf diese Werte außerhalb des Bereichs stimmen möglicherweise nicht genau überein.
Datenintegrität:
- Milvus parst oder transformiert JSON-Schlüssel nicht über das von Ihnen angegebene Casting hinaus. Wenn die Quelldaten inkonsistent sind (z. B. speichern einige Zeilen einen String für den Schlüssel
"k", während andere eine Zahl speichern), werden einige Zeilen nicht indiziert.
- Milvus parst oder transformiert JSON-Schlüssel nicht über das von Ihnen angegebene Casting hinaus. Wenn die Quelldaten inkonsistent sind (z. B. speichern einige Zeilen einen String für den Schlüssel
Indizieren eines Vektorfeldes
Im folgenden Beispiel wird ein Index für das Vektorfeld embedding erstellt, wobei der Indextyp AUTOINDEX verwendet wird. Bei diesem Typ wählt Milvus automatisch den am besten geeigneten Index auf der Grundlage des Datentyps aus. Sie können auch den Indextyp und die Parameter für jedes Feld anpassen. Details finden Sie unter Index erklärt.
# Set index params
# Index `embedding` with AUTOINDEX and specify similarity metric type
index_params.add_index(
field_name="embedding",
index_name="vector_index",
index_type="AUTOINDEX", # Use automatic indexing to simplify complex index settings
metric_type="COSINE" # Specify similarity metric type, options include L2, COSINE, or IP
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
indexes.add(IndexParam.builder()
.fieldName("embedding")
.indexName("vector_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE)
.build());
vectorIndex := index.NewAutoIndex(entity.COSINE)
indexOpt := milvusclient.NewCreateIndexOption("my_collection", "embedding", vectorIndex)
indexParams.push({
index_name: 'embedding_index',
field_name: 'embedding',
index_name: 'vector_index',
metricType: MetricType.CONSINE,
index_type: IndexType.AUTOINDEX,
));
export indexParams='[
{
"fieldName": "embedding",
"indexName": "vector_index",
"metricType": "COSINE",
"indexType": "AUTOINDEX"
}
]'
Sammlung erstellen
Sobald das Schema und der Index definiert sind, erstellen Sie eine Sammlung, die das JSON-Feld enthält.
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params
)
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOpt1, indexOpt2, indexOpt))
if err != nil {
fmt.Println(err.Error())
// handler err
}
await client.create_collection({
collection_name: "my_collection",
schema: schema,
index_params: indexParams
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
Daten einfügen
Nach der Erstellung der Sammlung fügen Sie Entitäten ein, die dem Schema entsprechen.
# Sample data
data = [
{
"metadata": {
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": True,
"tags": ["summer_sale"]
},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": None, # Entire JSON object is null
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
# JSON field is completely missing
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
},
{
# Some sub-keys are null
"metadata": {
"product_info": {"category": None, "brand": "BrandB"},
"price": 59.99,
"in_stock": None
},
"pk": 4,
"embedding": [0.56, 0.38, 0.21]
}
]
client.insert(
collection_name="my_collection",
data=data
)
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
rows.add(gson.fromJson("{\"metadata\":{\"product_info\":{\"category\":\"electronics\",\"brand\":\"BrandA\"},\"price\":99.99,\"in_stock\":True,\"tags\":[\"summer_sale\"]},\"pk\":1,\"embedding\":[0.12,0.34,0.56]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\":null,\"pk\":2,\"embedding\":[0.56,0.78,0.90]}", JsonObject.class));
rows.add(gson.fromJson("{\"pk\":3,\"embedding\":[0.91,0.18,0.23]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\":{\"product_info\":{\"category\":null,\"brand\":\"BrandB\"},\"price\":59.99,\"in_stock\":null},\"pk\":4,\"embedding\":[0.56,0.38,0.21]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(rows)
.build());
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("pk", []int64{1, 2, 3, 4}).
WithFloatVectorColumn("embedding", 3, [][]float32{
{0.12, 0.34, 0.56},
{0.56, 0.78, 0.90},
{0.91, 0.18, 0.23},
{0.56, 0.38, 0.21},
}).WithColumns(
column.NewColumnJSONBytes("metadata", [][]byte{
[]byte(`{
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": True,
"tags": ["summer_sale"]
}`),
[]byte(`null`),
[]byte(`null`),
[]byte(`"metadata": {
"product_info": {"category": None, "brand": "BrandB"},
"price": 59.99,
"in_stock": None
}`),
}),
))
if err != nil {
fmt.Println(err.Error())
// handle err
}
const data = [
{
"metadata": {
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": True,
"tags": ["summer_sale"]
},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": None, # Entire JSON object is null
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
# JSON field is completely missing
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
},
{
# Some sub-keys are null
"metadata": {
"product_info": {"category": None, "brand": "BrandB"},
"price": 59.99,
"in_stock": None
},
"pk": 4,
"embedding": [0.56, 0.38, 0.21]
}
];
await client.insert({
collection_name: "my_collection",
data: data
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"data": [
{
"metadata": {
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": true,
"tags": ["summer_sale"]
},
"varchar_field2": "High quality product",
"pk": 1,
"embedding": [0.1, 0.2, 0.3]
},
{
"metadata": null,
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
},
{
"metadata": {
"product_info": {"category": null, "brand": "BrandB"},
"price": 59.99,
"in_stock": null
},
"pk": 4,
"embedding": [0.56, 0.38, 0.21]
}
],
"collectionName": "my_collection"
}'
Abfrage mit Filterausdrücken
Verwenden Sie nach dem Einfügen von Entitäten die Methode query, um Entitäten abzurufen, die mit den angegebenen Filterausdrücken übereinstimmen.
Für JSON-Felder, die Nullwerte zulassen, wird das Feld als Null behandelt, wenn das gesamte JSON-Objekt fehlt oder auf None gesetzt ist. Weitere Informationen finden Sie unter JSON-Felder mit Nullwerten.
Um Entitäten abzurufen, bei denen metadata nicht null ist:
# Query to filter out records with null metadata
filter = 'metadata is not null'
res = client.query(
collection_name="my_collection",
filter=filter,
output_fields=["metadata", "pk"]
)
# Expected result:
# Rows with pk=1 and pk=4 have valid, non-null metadata.
# Rows with pk=2 (metadata=None) and pk=3 (no metadata key) are excluded.
print(res)
# Output:
# data: [
# "{'metadata': {'product_info': {'category': 'electronics', 'brand': 'BrandA'}, 'price': 99.99, 'in_stock': True, 'tags': ['summer_sale']}, 'pk': 1}",
# "{'metadata': {'product_info': {'category': None, 'brand': 'BrandB'}, 'price': 59.99, 'in_stock': None}, 'pk': 4}"
# ]
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
String filter = "metadata is not null";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter(filter)
.outputFields(Arrays.asList("metadata", "pk"))
.build());
System.out.println(resp.getQueryResults());
// Output
//
// [
// QueryResp.QueryResult(entity={metadata={"product_info":{"category":"electronics","brand":"BrandA"},"price":99.99,"in_stock":true,"tags":["summer_sale"]}, pk=1}),
// QueryResp.QueryResult(entity={metadata={"product_info":{"category":null,"brand":"BrandB"},"price":59.99,"in_stock":null}, pk=4})
// ]
filter := "metadata is not null"
rs, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter(filter).
WithOutputFields("metadata", "pk"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println("pk", rs.GetColumn("pk").FieldData().GetScalars())
fmt.Println("metadata", rs.GetColumn("metadata").FieldData().GetScalars())
await client.query({
collection_name: 'my_scalar_collection',
filter: 'metadata["category"] == "electronics" and metadata["price"] < 150',
output_fields: ['metadata']
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"filter": "metadata is not null",
"outputFields": ["metadata", "pk"]
}'
#{"code":0,"cost":0,"data":[{"metadata":"{\"product_info\": {\"category\": \"electronics\", \"brand\": \"BrandA\"}, \"price\": 99.99, \"in_stock\": true, \"tags\": [\"summer_sale\"]}","pk":1},{"metadata":"","pk":2},{"metadata":"","pk":3},{"metadata":"{\"product_info\": {\"category\": null, \"brand\": \"BrandB\"}, \"price\": 59.99, \"in_stock\": null}","pk":4}]}
Zum Abrufen von Entitäten, bei denen metadata["product_info"]["category"] gleich "electronics" ist:
filter = 'metadata["product_info"]["category"] == "electronics"'
res = client.query(
collection_name="my_collection",
filter=filter,
output_fields=["metadata", "pk"]
)
# Expected result:
# - Only pk=1 has "category": "electronics".
# - pk=4 has "category": None, so it doesn't match.
# - pk=2 and pk=3 have no valid metadata.
print(res)
# Output:
# data: [
# "{'pk': 1, 'metadata': {'product_info': {'category': 'electronics', 'brand': 'BrandA'}, 'price': 99.99, 'in_stock': True, 'tags': ['summer_sale']}}"
# ]
String filter = "metadata[\"product_info\"][\"category\"] == \"electronics\"";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter(filter)
.outputFields(Arrays.asList("metadata", "pk"))
.build());
System.out.println(resp.getQueryResults());
// Output
// [QueryResp.QueryResult(entity={metadata={"product_info":{"category":"electronics","brand":"BrandA"},"price":99.99,"in_stock":true,"tags":["summer_sale"]}, pk=1})]
filter = `metadata["product_info"]["category"] == "electronics"`
rs, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter(filter).
WithOutputFields("metadata", "pk"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println("pk", rs.GetColumn("pk").FieldData().GetScalars())
fmt.Println("metadata", rs.GetColumn("metadata").FieldData().GetScalars())
const filter = 'metadata["category"] == "electronics"';
const res = await client.query({
collection_name: "my_collection",
filter: filter,
output_fields: ["metadata", "pk"]
});
// Example output:
// {
//. data: [
// {'pk': 1, 'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}}
// ]
// }
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"filter": "metadata[\"product_info\"][\"category\"] == \"electronics\"",
"outputFields": ["metadata", "pk"]
}'
#{"code":0,"cost":0,"data":[{"metadata":"{\"product_info\": {\"category\": \"electronics\", \"brand\": \"BrandA\"}, \"price\": 99.99, \"in_stock\": true, \"tags\": [\"summer_sale\"]}","pk":1}]}
Vektorsuche mit Filterausdrücken
Zusätzlich zur grundlegenden skalaren Feldfilterung können Sie Vektorähnlichkeitssuchen mit skalaren Feldfiltern kombinieren. Der folgende Code zeigt zum Beispiel, wie man einen Skalarfeldfilter zu einer Vektorsuche hinzufügt:
filter = 'metadata["product_info"]["brand"] == "BrandA"'
res = client.search(
collection_name="my_collection",
data=[[0.3, -0.6, 0.1]],
limit=5,
search_params={"params": {"nprobe": 10}},
output_fields=["metadata"],
filter=filter
)
# Expected result:
# - Only pk=1 has "brand": "BrandA" in metadata["product_info"].
# - pk=4 has "brand": "BrandB".
# - pk=2 and pk=3 have no valid metadata.
# Hence, only pk=1 matches the filter.
print(res)
# Output:
# data: [
# "[{'id': 1, 'distance': -0.2479381263256073, 'entity': {'metadata': {'product_info': {'category': 'electronics', 'brand': 'BrandA'}, 'price': 99.99, 'in_stock': True, 'tags': ['summer_sale']}}}]"
# ]
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
String filter = "metadata[\"product_info\"][\"brand\"] == \"BrandA\"";
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_collection")
.annsField("embedding")
.data(Collections.singletonList(new FloatVec(new float[]{0.3f, -0.6f, 0.1f})))
.topK(5)
.outputFields(Collections.singletonList("metadata"))
.filter(filter)
.build());
System.out.println(resp.getSearchResults());
// Output
//
// [
// [
// SearchResp.SearchResult(entity={metadata={"product_info":{"category":"electronics","brand":"BrandA"},"price":99.99,"in_stock":true,"tags":["summer_sale"]}}, score=-0.24793813, id=1)
// ]
// ]
queryVector := []float32{0.3, -0.6, -0.1}
filter = "metadata[\"product_info\"][\"brand\"] == \"BrandA\""
annParam := index.NewCustomAnnParam()
annParam.WithExtraParam("nprobe", 10)
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"my_collection", // collectionName
5, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("embedding").
WithFilter(filter).
WithOutputFields("metadata").
WithAnnParam(annParam))
if err != nil {
fmt.Println(err.Error())
// handle error
}
for _, resultSet := range resultSets {
fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
fmt.Println("Scores: ", resultSet.Scores)
fmt.Println("metadata", resultSet.GetColumn("metadata").FieldData().GetScalars())
}
await client.search({
collection_name: 'my_collection',
data: [0.3, -0.6, 0.1],
limit: 5,
output_fields: ['metadata'],
filter: 'metadata["category"] == "electronics" and metadata["price"] < 150',
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"data": [
[0.3, -0.6, 0.1]
],
"annsField": "embedding",
"limit": 5,
"searchParams": {
"params": {
"nprobe": 10
}
},
"outputFields": ["metadata"],
"filter": "metadata[\"product_info\"][\"brand\"] == \"BrandA\""
}'
##{"code":0,"cost":0,"data":[{"metadata":"{\"product_info\": {\"category\": \"electronics\", \"brand\": \"BrandA\"}, \"price\": 99.99, \"in_stock\": true, \"tags\": [\"summer_sale\"]}","pk":1}]}
Darüber hinaus unterstützt Milvus erweiterte JSON-Filteroperatoren wie JSON_CONTAINS, JSON_CONTAINS_ALL und JSON_CONTAINS_ANY, die die Abfragemöglichkeiten weiter verbessern können. Weitere Einzelheiten finden Sie unter JSON-Operatoren.