Champ dynamique
Milvus vous permet d'insérer des entités avec des structures flexibles et évolutives grâce à une fonctionnalité spéciale appelée champ dynamique. Ce champ est mis en œuvre sous la forme d'un champ JSON caché appelé $meta, qui stocke automatiquement tous les champs de vos données qui ne sont pas explicitement définis dans le schéma de la collection.
Fonctionnement
Lorsque le champ dynamique est activé, Milvus ajoute un champ caché $meta à chaque entité. Ce champ est de type JSON, ce qui signifie qu'il peut stocker toute structure de données compatible JSON et peut être indexé à l'aide de la syntaxe de chemin JSON.
Lors de l'insertion de données, tout champ non déclaré dans le schéma est automatiquement stocké sous la forme d'une paire clé-valeur à l'intérieur de ce champ dynamique.
Vous n'avez pas besoin de gérer $meta manuellement : Milvus le fait de manière transparente.
Par exemple, si votre schéma de collection définit uniquement id et vector, et que vous insérez l'entité suivante :
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"name": "Item A", // Not in schema
"category": "books" // Not in schema
}
Lorsque la fonction de champ dynamique est activée, Milvus la stocke en interne en tant que :
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"$meta": {
"name": "Item A",
"category": "books"
}
}
Cela vous permet de faire évoluer votre structure de données sans modifier le schéma.
Les cas d'utilisation courants sont les suivants
Stockage de champs facultatifs ou rarement récupérés
Capturer des métadonnées qui varient selon l'entité
Prise en charge d'un filtrage flexible via des index sur des clés de champs dynamiques spécifiques
Types de données pris en charge
Le champ dynamique prend en charge tous les types de données scalaires fournis par Milvus, y compris les valeurs simples et complexes. Ces types de données s'appliquent aux **valeurs des clés stockées dans $meta.
Les types pris en charge sont les suivants
Chaîne (
VARCHAR)Entier (
INT8,INT32,INT64)Virgule flottante (
FLOAT,DOUBLE)Booléen (
BOOL)Tableau de valeurs scalaires (
ARRAY)Objets JSON (
JSON)
Exemple :
{
"brand": "Acme",
"price": 29.99,
"in_stock": true,
"tags": ["new", "hot"],
"specs": {
"weight": "1.2kg",
"dimensions": { "width": 10, "height": 20 }
}
}
Chacune des clés et valeurs ci-dessus serait stockée dans le champ $meta.
Activer le champ dynamique
Pour utiliser la fonctionnalité de champ dynamique, définissez enable_dynamic_field=True lors de la création du schéma de la collection :
from pymilvus import MilvusClient, DataType
# Initialize client
client = MilvusClient(uri="http://localhost:19530")
# Create schema with dynamic field enabled
schema = client.create_schema(
auto_id=False,
enable_dynamic_field=True,
)
# Add explicitly defined fields
schema.add_field(field_name="my_id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="my_vector", datatype=DataType.FLOAT_VECTOR, dim=5)
# Create the collection
client.create_collection(
collection_name="my_collection",
schema=schema
)
import io.milvus.v2.client.*;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.AddFieldReq;
ConnectConfig config = ConnectConfig.builder()
.uri("http://localhost:19530")
.build();
MilvusClientV2 client = new MilvusClientV2(config);
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
.enableDynamicField(true)
.build();
schema.addField(AddFieldReq.builder()
.fieldName("my_id")
.dataType(DataType.Int64)
.isPrimaryKey(Boolean.TRUE)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("my_vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.build();
client.createCollection(requestCreate);
import { MilvusClient, DataType, CreateCollectionReq } from '@zilliz/milvus2-sdk-node';
// Initialize client
const client = new MilvusClient({ address: 'localhost:19530' });
// Create collection
const res = await client.createCollection({
collection_name: 'my_collection',
schema: [
{
name: 'my_id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: false,
},
{
name: 'my_vector',
data_type: DataType.FloatVector,
type_params: {
dim: '5',
}
],
enable_dynamic_field: true
});
import (
"context"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "localhost:19530",
})
if err != nil {
return err
}
schema := entity.NewSchema().WithDynamicFieldEnabled(true)
schema.WithField(entity.NewField().
WithName("my_id").pk
WithDataType(entity.FieldTypeInt64).
WithIsPrimaryKey(true),
).WithField(entity.NewField().
WithName("my_vector").
WithDataType(entity.FieldTypeFloatVector).
WithDim(5),
)
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema))
if err != nil {
return err
}
# restful
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export myIdField='{
"fieldName": "my_id",
"dataType": "Int64",
"isPrimary": true,
"autoID": false
}'
export myVectorField='{
"fieldName": "my_vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 5
}
}'
export schema="{
\"autoID\": false,
\"enableDynamicField\": true,
\"fields\": [
$myIdField,
$myVectorField
]
}"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"schema\": $schema
}"
Insérer des entités dans la collection
Le champ dynamique vous permet d'insérer des champs supplémentaires non définis dans le schéma. Ces champs seront stockés automatiquement dans $meta.
entities = [
{
"my_id": 1, # Explicitly defined primary field
"my_vector": [0.1, 0.2, 0.3, 0.4, 0.5], # Explicitly defined vector field
"overview": "Great product", # Scalar key not defined in schema
"words": 150, # Scalar key not defined in schema
"dynamic_json": { # JSON key not defined in schema
"varchar": "some text",
"nested": {
"value": 42.5
},
"string_price": "99.99" # Number stored as string
}
}
]
client.insert(collection_name="my_collection", data=entities)
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
Gson gson = new Gson();
JsonObject row = new JsonObject();
row.addProperty("my_id", 1);
row.add("my_vector", gson.toJsonTree(Arrays.asList(0.1, 0.2, 0.3, 0.4, 0.5)));
row.addProperty("overview", "Great product");
row.addProperty("words", 150);
JsonObject dynamic = new JsonObject();
dynamic.addProperty("varchar", "some text");
dynamic.addProperty("string_price", "99.99");
JsonObject nested = new JsonObject();
nested.addProperty("value", 42.5);
dynamic.add("nested", nested);
row.add("dynamic_json", dynamic);
client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(row))
.build());
const entities = [
{
my_id: 1,
my_vector: [0.1, 0.2, 0.3, 0.4, 0.5],
overview: 'Great product',
words: 150,
dynamic_json: {
varchar: 'some text',
nested: {
value: 42.5,
},
string_price: '99.99',
},
},
];
const res = await client.insert({
collection_name: 'my_collection',
data: entities,
});
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("my_id", []int64{1}).
WithFloatVectorColumn("my_vector", 5, [][]float32{
{0.1, 0.2, 0.3, 0.4, 0.5},
}).WithColumns(
column.NewColumnVarChar("overview", []string{"Great product"}),
column.NewColumnInt32("words", []int32{150}),
column.NewColumnJSONBytes("dynamic_json", [][]byte{
[]byte(`{
varchar: 'some text',
nested: {
value: 42.5,
},
string_price: '99.99',
}`),
}),
))
if err != nil {
return err
}
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"data": [
{
"my_id": 1,
"my_vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"overview": "Great product",
"words": 150,
"dynamic_json": {
"varchar": "some text",
"nested": {
"value": 42.5
},
"string_price": "99.99"
}
}
],
"collectionName": "my_collection"
}'
Indexation des clés dans le champ dynamiqueCompatible with Milvus 2.5.11+
Milvus vous permet d'utiliser l'indexation par chemin JSON pour créer des index sur des clés spécifiques dans le champ dynamique. Il peut s'agir de valeurs scalaires ou de valeurs imbriquées dans des objets JSON.
L'indexation des clés de champ dynamique est facultative. Il est toujours possible d'effectuer des requêtes ou des filtrages sur les clés des champs dynamiques sans index, mais les performances risquent d'être moins bonnes en raison de la recherche par force brute.
Syntaxe d'indexation des chemins JSON
Pour créer un index de chemin JSON, spécifiez :
JSON path (
json_path) : Le chemin d'accès à la clé ou au champ imbriqué dans votre objet JSON que vous souhaitez indexer.Exemple :
metadata["category"]Ceci définit l'endroit où le moteur d'indexation doit regarder à l'intérieur de la structure JSON.
JSON cast type (
json_cast_type) : Le type de données que Milvus doit utiliser lors de l'interprétation et de l'indexation de la valeur au chemin spécifié.Ce type doit correspondre au type de données réel du champ indexé.
Pour obtenir une liste complète, reportez-vous à la section Types de cast JSON pris en charge.
Utiliser le chemin JSON pour indexer les clés des champs dynamiques
Étant donné que le champ dynamique est un champ JSON, vous pouvez indexer n'importe quelle clé qu'il contient à l'aide de la syntaxe de chemin d'accès JSON. Cette méthode fonctionne aussi bien pour les valeurs scalaires simples que pour les structures complexes imbriquées.
Exemples de chemins JSON :
Pour les clés simples :
overview,wordsPour les clés imbriquées :
dynamic_json['varchar'],dynamic_json['nested']['value']
index_params = client.prepare_index_params()
# Index a simple string key
index_params.add_index(
field_name="overview", # Key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="overview_index", # Unique index name
params={
"json_cast_type": "varchar", # Data type that Milvus uses when indexing the values
"json_path": "overview" # JSON path to the key
}
)
# Index a simple numeric key
index_params.add_index(
field_name="words", # Key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="words_index", # Unique index name
params={
"json_cast_type": "double", # Data type that Milvus uses when indexing the values
"json_path": "words" # JSON path to the key
}
)
# Index a nested key within a JSON object
index_params.add_index(
field_name="dynamic_json", # JSON key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="json_varchar_index", # Unique index name
params={
"json_cast_type": "varchar", # Data type that Milvus uses when indexing the values
"json_path": "dynamic_json['varchar']" # JSON path to the nested key
}
)
# Index a deeply nested key
index_params.add_index(
field_name="dynamic_json",
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="json_nested_index", # Unique index name
params={
"json_cast_type": "double",
"json_path": "dynamic_json['nested']['value']"
}
)
import io.milvus.v2.common.IndexParam;
Map<String,Object> extraParams1 = new HashMap<>();
extraParams1.put("json_path", "overview");
extraParams1.put("json_cast_type", "varchar");
indexParams.add(IndexParam.builder()
.fieldName("overview")
.indexName("overview_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams1)
.build());
Map<String,Object> extraParams2 = new HashMap<>();
extraParams2.put("json_path", "words");
extraParams2.put("json_cast_type", "double");
indexParams.add(IndexParam.builder()
.fieldName("words")
.indexName("words_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams2)
.build());
Map<String,Object> extraParams3 = new HashMap<>();
extraParams3.put("json_path", "dynamic_json['varchar']");
extraParams3.put("json_cast_type", "varchar");
indexParams.add(IndexParam.builder()
.fieldName("dynamic_json")
.indexName("json_varchar_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams3)
.build());
Map<String,Object> extraParams4 = new HashMap<>();
extraParams4.put("json_path", "dynamic_json['nested']['value']");
extraParams4.put("json_cast_type", "double");
indexParams.add(IndexParam.builder()
.fieldName("dynamic_json")
.indexName("json_nested_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams4)
.build());
const indexParams = [
{
collection_name: 'my_collection',
field_name: 'overview',
index_name: 'overview_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_path: 'overview',
json_cast_type: 'varchar',
},
},
{
collection_name: 'my_collection',
field_name: 'words',
index_name: 'words_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_path: 'words',
json_cast_type: 'double',
},
},
{
collection_name: 'my_collection',
field_name: 'dynamic_json',
index_name: 'json_varchar_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_cast_type: 'varchar',
json_path: "dynamic_json['varchar']",
},
},
{
collection_name: 'my_collection',
field_name: 'dynamic_json',
index_name: 'json_nested_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_cast_type: 'double',
json_path: "dynamic_json['nested']['value']",
},
},
];
import (
"github.com/milvus-io/milvus/client/v2/index"
)
jsonIndex1 := index.NewJSONPathIndex(index.AUTOINDEX, "varchar", "overview")
.WithIndexName("overview_index")
jsonIndex2 := index.NewJSONPathIndex(index.AUTOINDEX, "double", "words")
.WithIndexName("words_index")
jsonIndex3 := index.NewJSONPathIndex(index.AUTOINDEX, "varchar", `dynamic_json['varchar']`)
.WithIndexName("json_varchar_index")
jsonIndex4 := index.NewJSONPathIndex(index.AUTOINDEX, "double", `dynamic_json['nested']['value']`)
.WithIndexName("json_nested_index")
indexOpt1 := milvusclient.NewCreateIndexOption("my_collection", "overview", jsonIndex1)
indexOpt2 := milvusclient.NewCreateIndexOption("my_collection", "words", jsonIndex2)
indexOpt3 := milvusclient.NewCreateIndexOption("my_collection", "dynamic_json", jsonIndex3)
indexOpt4 := milvusclient.NewCreateIndexOption("my_collection", "dynamic_json", jsonIndex4)
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export overviewIndex='{
"fieldName": "dynamic_json",
"indexName": "overview_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "varchar",
"json_path": "dynamic_json[\"overview\"]"
}
}'
export wordsIndex='{
"fieldName": "dynamic_json",
"indexName": "words_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "double",
"json_path": "dynamic_json[\"words\"]"
}
}'
export varcharIndex='{
"fieldName": "dynamic_json",
"indexName": "json_varchar_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "varchar",
"json_path": "dynamic_json[\"varchar\"]"
}
}'
export nestedIndex='{
"fieldName": "dynamic_json",
"indexName": "json_nested_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "double",
"json_path": "dynamic_json[\"nested\"][\"value\"]"
}
}'
Utiliser les fonctions JSON cast pour la conversion de typeCompatible with Milvus 2.5.14+
Si la clé d'un champ dynamique contient des valeurs dans un format incorrect (par exemple, des nombres stockés sous forme de chaînes), vous pouvez utiliser une fonction cast pour les convertir :
# Convert a string to double before indexing
index_params.add_index(
field_name="dynamic_json", # JSON key name
index_type="AUTOINDEX",
index_name="json_string_price_index",
params={
"json_path": "dynamic_json['string_price']",
"json_cast_type": "double", # Must be the output type of the cast function
"json_cast_function": "STRING_TO_DOUBLE" # Case insensitive; convert string to double
}
)
Map<String,Object> extraParams5 = new HashMap<>();
extraParams5.put("json_path", "dynamic_json['string_price']");
extraParams5.put("json_cast_type", "double");
indexParams.add(IndexParam.builder()
.fieldName("dynamic_json")
.indexName("json_string_price_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams5)
.build());
indexParams.push({
collection_name: 'my_collection',
field_name: 'dynamic_json',
index_name: 'json_string_price_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_path: "dynamic_json['string_price']",
json_cast_type: 'double',
json_cast_function: 'STRING_TO_DOUBLE',
},
});
jsonIndex5 := index.NewJSONPathIndex(index.AUTOINDEX, "double", `dynamic_json['string_price']`)
.WithIndexName("json_string_price_index")
indexOpt5 := milvusclient.NewCreateIndexOption("my_collection", "dynamic_json", jsonIndex5)
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export stringPriceIndex='{
"fieldName": "dynamic_json",
"indexName": "json_string_price_index",
"params": {
"index_type": "AUTOINDEX",
"json_path": "dynamic_json[\"string_price\"]",
"json_cast_type": "double",
"json_cast_function": "STRING_TO_DOUBLE"
}
}'
Si la conversion de type échoue (par exemple, la valeur
"not_a_number"ne peut pas être convertie en nombre), la valeur est ignorée et non indexée.Pour plus de détails sur les paramètres de la fonction cast, voir Champ JSON.
Appliquer des index à la collection
Après avoir défini les paramètres d'index, vous pouvez les appliquer à la collection à l'aide de create_index():
client.create_index(
collection_name="my_collection",
index_params=index_params
)
import io.milvus.v2.service.index.request.CreateIndexReq;
client.createIndex(CreateIndexReq.builder()
.collectionName("my_collection")
.indexParams(indexParams)
.build());
await client.createIndex(indexParams);
indexTask1, err := client.CreateIndex(ctx, indexOpt1)
if err != nil {
return err
}
indexTask2, err := client.CreateIndex(ctx, indexOpt2)
if err != nil {
return err
}
indexTask3, err := client.CreateIndex(ctx, indexOpt3)
if err != nil {
return err
}
indexTask4, err := client.CreateIndex(ctx, indexOpt4)
if err != nil {
return err
}
indexTask5, err := client.CreateIndex(ctx, indexOpt5)
if err != nil {
return err
}
# restful
export indexParams="[
$varcharIndex,
$nestedIndex,
$overviewIndex,
$wordsIndex,
$stringPriceIndex
]"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"indexParams\": $indexParams
}"
Filtrer par clé de champ dynamique
Après avoir inséré des entités avec des clés de champ dynamiques, vous pouvez les filtrer à l'aide d'expressions de filtrage standard.
Pour les clés non JSON (par exemple les chaînes, les nombres, les booléens), vous pouvez les référencer directement par le nom de la clé.
Pour les clés stockant des objets JSON, utilisez la syntaxe de chemin JSON pour accéder aux valeurs imbriquées.
En se basant sur l 'exemple d'entité de la section précédente, les expressions de filtrage valides sont les suivantes :
filter = 'overview == "Great product"' # Non-JSON key
filter = 'words >= 100' # Non-JSON key
filter = 'dynamic_json["nested"]["value"] < 50' # JSON object key
String filter = 'overview == "Great product"';
String filter = 'words >= 100';
String filter = 'dynamic_json["nested"]["value"] < 50';
filter = 'overview == "Great product"' // Non-JSON key
filter = 'words >= 100' // Non-JSON key
filter = 'dynamic_json["nested"]["value"] < 50' // JSON object key
filter := 'overview == "Great product"'
filter := 'words >= 100'
filter := 'dynamic_json["nested"]["value"] < 50'
# restful
export filterOverview='overview == "Great product"'
export filterWords='words >= 100'
export filterNestedValue='dynamic_json["nested"]["value"] < 50'
Récupération des clés de champ dynamiques: Pour renvoyer des clés de champ dynamiques dans les résultats d'une recherche ou d'une requête, vous devez les spécifier explicitement dans le paramètre output_fields en utilisant la même syntaxe de chemin d'accès JSON que pour le filtrage :
# Example: Include dynamic field keys in search results
results = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.3, 0.4, 0.5]],
filter=filter, # Filter expression defined earlier
limit=10,
output_fields=[
"overview", # Simple dynamic field key
'dynamic_json["varchar"]' # Nested JSON key
]
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.SearchReq
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
FloatVec queryVector = new FloatVec(new float[]{0.1, 0.2, 0.3, 0.4, 0.5});
SearchReq searchReq = SearchReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(queryVector))
.topK(5)
.filter(filter)
.outputFields(Arrays.asList("overview", "dynamic_json['varchar']"))
.build();
SearchResp searchResp = client.search(searchReq);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const address = "YOUR_CLUSTER_ENDPOINT";
const token = "YOUR_CLUSTER_TOKEN";
const client = new MilvusClient({address, token});
const query_vector = [0.1, 0.2, 0.3, 0.4, 0.5]
const res = await client.search({
collection_name: "my_collection",
data: [query_vector],
limit: 5,
filters: filter,
output_fields: ["overview", "dynamic_json['varchar']"]
})
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "YOUR_CLUSTER_ENDPOINT"
token := "YOUR_CLUSTER_TOKEN"
client, err := client.New(ctx, &client.ClientConfig{
Address: milvusAddr,
APIKey: token,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
queryVector := []float32{0.1, 0.2, 0.3, 0.4, 0.5}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"my_collection", // collectionName
5, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithConsistencyLevel(entity.ClStrong).
WithANNSField("my_vector").
WithFilter(filter).
WithOutputFields("overview", "dynamic_json['varchar']"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
export FILTER='color like "red%" and likes > 50'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"data\": [
[0.1, 0.2, 0.3, 0.4, 0.5]
],
\"annsField\": \"my_vector\",
\"filter\": \"${FILTER}\",
\"limit\": 5,
\"outputFields\": [\"overview\", \"dynamic_json.varchar\"]
}"
Les clés de champ dynamiques ne sont pas incluses par défaut dans les résultats et doivent être explicitement demandées.
Pour obtenir la liste complète des opérateurs et des expressions de filtrage pris en charge, reportez-vous à la section Recherche filtrée.
Assembler le tout
Vous avez maintenant appris à utiliser le champ dynamique pour stocker et indexer de manière flexible des clés qui ne sont pas définies dans le schéma. Une fois qu'une clé de champ dynamique est insérée, vous pouvez l'utiliser comme n'importe quel autre champ dans les expressions de filtre, sans syntaxe particulière.
Pour compléter le flux de travail dans une application réelle, vous devrez également
Créer un index sur votre champ vectoriel (obligatoire pour chaque collection)
Reportez-vous à la section Définir les paramètres de l'index.
Charger la collection
Voir Charger et libérer
Effectuer une recherche ou une requête à l'aide de filtres de chemin JSON
Voir Recherche filtrée et opérateurs JSON
FAQ
Quand dois-je définir un champ explicitement dans le schéma au lieu d'utiliser une clé de champ dynamique ?
Vous devez définir un champ explicitement dans le schéma au lieu d'utiliser une clé de champ dynamique dans les cas suivants :
Le champ est souvent inclus dans output_fields: Seuls les champs définis explicitement sont garantis d'être récupérés efficacement via
output_fields. Les clés de champ dynamiques ne sont pas optimisées pour la recherche à haute fréquence et peuvent entraîner des surcoûts de performance.Le champ est fréquemment consulté ou filtré: Bien que l'indexation d'une clé de champ dynamique puisse offrir des performances de filtrage similaires à celles des champs de schéma fixes, les champs explicitement définis offrent une structure plus claire et une meilleure maintenabilité.
Vous avez besoin d'un contrôle total sur le comportement du champ: Les champs explicites prennent en charge les contraintes et les validations au niveau du schéma, ainsi qu'un typage plus clair, ce qui peut s'avérer utile pour gérer l'intégrité et la cohérence des données.
Vous voulez éviter les incohérences d'indexation: Les données contenues dans les clés de champ dynamiques sont plus susceptibles de présenter des incohérences au niveau du type ou de la structure. L'utilisation d'un schéma fixe permet de garantir la qualité des données, en particulier si vous prévoyez d'utiliser l'indexation ou la distribution.
Puis-je créer plusieurs index sur la même clé de champ dynamique avec des types de données différents ?
Non, vous ne pouvez créer qu'un seul index par chemin JSON. Même si une clé de champ dynamique contient des valeurs de type mixte (par exemple, des chaînes et des nombres), vous devez choisir une seule adresse json_cast_type lorsque vous indexez ce chemin. Les index multiples sur la même clé avec des types différents ne sont pas pris en charge pour le moment.
Lors de l'indexation d'une clé de champ dynamique, que se passe-t-il si la conversion des données échoue ?
Si vous avez créé un index sur une clé de champ dynamique et que la conversion des données échoue (par exemple, une valeur censée être convertie en double est une chaîne non numérique telle que "abc"), ces valeurs spécifiques seront ignorées silencieusement lors de la création de l'index. Elles n'apparaîtront pas dans l'index et ne seront donc pas renvoyées dans les résultats des recherches basées sur des filtres ou des requêtes qui s'appuient sur l'index.
Ceci a quelques implications importantes :
Pas de retour à l'analyse complète: Si la majorité des entités sont indexées avec succès, les requêtes de filtrage s'appuieront entièrement sur l'index. Les entités dont le casting a échoué seront exclues de l'ensemble des résultats, même si elles correspondent logiquement à la condition de filtrage.
Risque de précision de la recherche: Dans les grands ensembles de données où la qualité des données est incohérente (en particulier dans les clés de champ dynamiques), ce comportement peut conduire à des résultats manquants inattendus. Il est essentiel d'assurer un formatage cohérent et valide des données avant l'indexation.
Utilisez les fonctions de conversion avec prudence: Si vous utilisez
json_cast_functionpour convertir des chaînes de caractères en nombres lors de l'indexation, assurez-vous que les valeurs des chaînes de caractères sont convertibles de manière fiable. Une inadéquation entrejson_cast_typeet le type réellement converti entraînera des erreurs ou des entrées ignorées.
Que se passe-t-il si ma requête utilise un type de données différent du type de cast indexé ?
Si votre requête compare une clé de champ dynamique en utilisant un type de données différent de celui utilisé dans l'index (par exemple, en effectuant une requête avec une comparaison de chaînes alors que l'index a été converti en double), le système n'utilisera pas l'index et pourra revenir à une analyse complète uniquement si cela est possible. Pour des performances et une précision optimales, assurez-vous que votre type de requête correspond à l'adresse json_cast_type utilisée lors de la création de l'index.