Campo dinâmico
O Milvus permite-lhe inserir entidades com estruturas flexíveis e evolutivas através de uma funcionalidade especial designada por campo dinâmico. Este campo é implementado como um campo JSON oculto chamado $meta, que armazena automaticamente quaisquer campos nos seus dados que não estejam explicitamente definidos no esquema da coleção.
Como funciona
Quando o campo dinâmico está ativado, o Milvus adiciona um campo $meta oculto a cada entidade. Este campo é do tipo JSON, o que significa que pode armazenar qualquer estrutura de dados compatível com JSON e pode ser indexado utilizando a sintaxe de caminho JSON.
Durante a inserção de dados, qualquer campo não declarado no esquema é automaticamente armazenado como um par chave-valor dentro deste campo dinâmico.
Não é necessário gerir o $meta manualmente - o Milvus trata-o de forma transparente.
Por exemplo, se o esquema da coleção definir apenas id e vector, e inserir a seguinte entidade:
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"name": "Item A", // Not in schema
"category": "books" // Not in schema
}
Com a funcionalidade de campo dinâmico activada, o Milvus armazena-a internamente como:
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"$meta": {
"name": "Item A",
"category": "books"
}
}
Isto permite-lhe evoluir a sua estrutura de dados sem alterar o esquema.
Casos de uso comuns incluem:
Armazenamento de campos opcionais ou de recuperação pouco frequente
Capturar metadados que variam consoante a entidade
Suporte de filtragem flexível através de índices em chaves de campo dinâmicas específicas
Tipos de dados suportados
O campo dinâmico suporta todos os tipos de dados escalares fornecidos pelo Milvus, incluindo valores simples e complexos. Estes tipos de dados aplicam-se aos **valores das chaves armazenadas em $meta.
Os tipos suportados incluem:
String (
VARCHAR)Inteiro (
INT8,INT32,INT64)Ponto flutuante (
FLOAT,DOUBLE)Booleano (
BOOL)Matriz de valores escalares (
ARRAY)Objectos JSON (
JSON)
Exemplo:
{
"brand": "Acme",
"price": 29.99,
"in_stock": true,
"tags": ["new", "hot"],
"specs": {
"weight": "1.2kg",
"dimensions": { "width": 10, "height": 20 }
}
}
Cada uma das chaves e valores acima seria armazenada no campo $meta.
Ativar o campo dinâmico
Para utilizar a funcionalidade de campo dinâmico, defina enable_dynamic_field=True ao criar o esquema de coleção:
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
}"
Inserir entidades na coleção
O campo dinâmico permite-lhe inserir campos extra não definidos no esquema. Estes campos serão armazenados automaticamente em $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"
}'
Chaves de índice no campo dinâmicoCompatible with Milvus 2.5.11+
O Milvus permite-lhe utilizar a indexação de caminhos JSON para criar índices em chaves específicas dentro do campo dinâmico. Estes podem ser valores escalares ou valores aninhados em objectos JSON.
A indexação das chaves do campo dinâmico é opcional. Ainda é possível consultar ou filtrar por chaves de campo dinâmico sem um índice, mas isso pode resultar num desempenho mais lento devido à pesquisa de força bruta.
Sintaxe de indexação de caminho JSON
Para criar um índice de caminho JSON, especifique:
Caminho JSON (
json_path): O caminho para a chave ou o campo aninhado no seu objeto JSON que pretende indexar.Exemplo:
metadata["category"]Isso define onde o mecanismo de indexação deve procurar dentro da estrutura JSON.
JSON cast type (
json_cast_type): O tipo de dados que o Milvus deve utilizar ao interpretar e indexar o valor no caminho especificado.Este tipo deve corresponder ao tipo de dados real do campo que está a ser indexado.
Para obter uma lista completa, consulte Tipos de elenco JSON suportados.
Usar o caminho JSON para indexar chaves de campo dinâmico
Como o campo dinâmico é um campo JSON, você pode indexar qualquer chave dentro dele usando a sintaxe de caminho JSON. Isso funciona tanto para valores escalares simples quanto para estruturas aninhadas complexas.
Exemplos de caminho JSON:
Para chaves simples:
overview,wordsPara chaves aninhadas:
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\"]"
}
}'
Utilizar funções de conversão JSON para conversão de tiposCompatible with Milvus 2.5.14+
Se uma chave de campo dinâmico contiver valores num formato incorreto (por exemplo, números armazenados como cadeias de caracteres), pode utilizar uma função de conversão para o converter:
# 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"
}
}'
Se a conversão de tipo falhar (por exemplo, o valor
"not_a_number"não pode ser convertido num número), o valor é ignorado e desindexado.Para obter detalhes sobre os parâmetros da função de conversão, consulte Campo JSON.
Aplicar índices à coleção
Depois de definir os parâmetros de índice, pode aplicá-los à coleção utilizando 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
}"
Filtrar por chaves de campo dinâmicas
Depois de inserir entidades com chaves de campo dinâmicas, pode filtrá-las utilizando expressões de filtro padrão.
Para chaves não JSON (por exemplo, strings, números, booleanos), pode referenciá-las diretamente pelo nome da chave.
Para chaves que armazenam objetos JSON, use a sintaxe de caminho JSON para acessar valores aninhados.
Com base na entidade de exemplo da secção anterior, as expressões de filtro válidas incluem:
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'
Recuperando chaves de campo dinâmicas: Para retornar chaves de campo dinâmicas nos resultados de pesquisa ou consulta, é necessário especificá-las explicitamente no parâmetro output_fields usando a mesma sintaxe de caminho JSON da filtragem:
# 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\"]
}"
As chaves de campo dinâmicas não são incluídas nos resultados por padrão e devem ser solicitadas explicitamente.
Para obter uma lista completa de operadores e expressões de filtro compatíveis, consulte Pesquisa filtrada.
Colocar tudo junto
Até agora, você aprendeu a usar o campo dinâmico para armazenar e indexar de forma flexível chaves que não estão definidas no esquema. Uma vez inserida uma chave de campo dinâmico, pode utilizá-la como qualquer outro campo em expressões de filtro, sem necessidade de sintaxe especial.
Para concluir o fluxo de trabalho numa aplicação do mundo real, também é necessário:
Criar um índice no seu campo de vetor (obrigatório para cada coleção)
Consulte Definir parâmetros de índice
Carregar a coleção
Consulte Carregar e liberar
Pesquisar ou consultar usando filtros de caminho JSON
Consulte Pesquisa filtrada e operadores JSON
PERGUNTAS FREQUENTES
Quando é que devo definir um campo explicitamente no esquema em vez de utilizar uma chave de campo dinâmica?
Deve definir um campo explicitamente no esquema em vez de utilizar uma chave de campo dinâmica quando:
O campo é frequentemente incluído em output_fields: Apenas os campos definidos explicitamente são garantidamente recuperáveis de forma eficiente através de
output_fields. As chaves de campo dinâmicas não são optimizadas para recuperação de alta frequência e podem incorrer em custos adicionais de desempenho.O campo é acedido ou filtrado frequentemente: Embora a indexação de uma chave de campo dinâmica possa proporcionar um desempenho de filtragem semelhante ao dos campos de esquema fixo, os campos explicitamente definidos oferecem uma estrutura mais clara e uma melhor manutenção.
É necessário um controlo total sobre o comportamento do campo: Os campos explícitos suportam restrições ao nível do esquema, validações e digitação mais clara, o que pode ser útil para gerir a integridade e consistência dos dados.
Você quer evitar inconsistências de indexação: Os dados em chaves de campo dinâmicas são mais propensos a inconsistências no tipo ou na estrutura. A utilização de um esquema fixo ajuda a garantir a qualidade dos dados, especialmente se planear utilizar indexação ou casting.
Posso criar vários índices na mesma chave de campo dinâmica com diferentes tipos de dados?
Não, você pode criar apenas um índice por caminho JSON. Mesmo que uma chave de campo dinâmico contenha valores de tipo misto (por exemplo, algumas cadeias de caracteres e alguns números), deve escolher um único json_cast_type ao indexar esse caminho. De momento, não são suportados vários índices na mesma chave com tipos diferentes.
Ao indexar uma chave de campo dinâmica, o que acontece se a conversão de dados falhar?
Se tiver criado um índice numa chave de campo dinâmico e a conversão de dados falhar - por exemplo, um valor destinado a ser convertido para double é uma cadeia de caracteres não numérica como "abc"- esses valores específicos serão ignorados silenciosamente durante a criação do índice. Eles não aparecerão no índice e, portanto, não serão retornados na pesquisa baseada em filtro ou nos resultados da consulta que dependem do índice.
Isto tem algumas implicações importantes:
Nenhum fallback para varredura completa: Se a maioria das entidades for indexada com êxito, as consultas de filtragem dependerão inteiramente do índice. As entidades com falhas de fundição serão excluídas do conjunto de resultados - mesmo que correspondam logicamente à condição do filtro.
Risco de precisão da pesquisa: Em grandes conjuntos de dados onde a qualidade dos dados é inconsistente (especialmente em chaves de campo dinâmicas), este comportamento pode levar a resultados inesperados em falta. É fundamental garantir uma formatação de dados consistente e válida antes da indexação.
Use funções de conversão com cautela: Se utilizar uma
json_cast_functionpara converter cadeias de caracteres em números durante a indexação, certifique-se de que os valores das cadeias de caracteres são convertíveis de forma fiável. Uma incompatibilidade entrejson_cast_typee o tipo convertido real resultará em erros ou entradas ignoradas.
O que acontece se a minha consulta utilizar um tipo de dados diferente do tipo de conversão indexado?
Se a sua consulta comparar uma chave de campo dinâmica utilizando um tipo de dados diferente do que foi utilizado no índice (por exemplo, uma consulta com uma comparação de cadeias de caracteres quando o índice foi convertido para double), o sistema não utilizará o índice e poderá voltar a uma pesquisa completa apenas se possível. Para obter o melhor desempenho e precisão, certifique-se de que o seu tipo de consulta corresponde ao json_cast_type utilizado durante a criação do índice.