Campo numerico
I campi numerici sono utilizzati per memorizzare dati numerici non vettoriali in Milvus. Questi campi sono in genere utilizzati per descrivere informazioni aggiuntive relative ai dati vettoriali, come l'età, il prezzo, ecc. Utilizzando questi dati, è possibile descrivere meglio i vettori e migliorare l'efficienza del filtraggio dei dati e delle query condizionali.
I campi numerici sono particolarmente utili in molti scenari. Ad esempio, nelle raccomandazioni per il commercio elettronico, un campo di prezzo può essere usato per filtrare; nell'analisi del profilo degli utenti, gli intervalli di età possono aiutare a raffinare i risultati. In combinazione con i dati vettoriali, i campi numerici possono aiutare il sistema a fornire ricerche simili e a soddisfare con maggiore precisione le esigenze personalizzate degli utenti.
Tipi di campi numerici supportati
Milvus supporta diversi tipi di campi numerici per soddisfare le diverse esigenze di archiviazione e interrogazione dei dati.
Tipo | Descrizione |
---|---|
| Tipo booleano per memorizzare |
| Numero intero a 8 bit, adatto per la memorizzazione di dati interi di piccole dimensioni. |
| Intero a 16 bit, per dati interi a medio raggio. |
| Intero a 32 bit, ideale per la memorizzazione di dati interi generici, come quantità di prodotti o ID utente. |
| Intero a 64 bit, adatto per la memorizzazione di dati a grande distanza, come timestamp o identificatori. |
| Numero in virgola mobile a 32 bit, per dati che richiedono una precisione generale, come le valutazioni o la temperatura. |
| Numero a virgola mobile a doppia precisione a 64 bit, per dati ad alta precisione come informazioni finanziarie o calcoli scientifici. |
Aggiungere un campo numerico
Per utilizzare i campi numerici in Milvus, definire i campi pertinenti nello schema della collezione, impostando datatype
su un tipo supportato come BOOL
o INT8
. Per un elenco completo dei tipi di campi numerici supportati, consultare la sezione Tipi di campi numerici supportati.
L'esempio seguente mostra come definire uno schema che includa i campi numerici age
e price
.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema(
auto_id=False,
enable_dynamic_fields=True,
)
schema.add_field(field_name="age", datatype=DataType.INT64)
schema.add_field(field_name="price", datatype=DataType.FLOAT)
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("age")
.dataType(DataType.Int64)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("price")
.dataType(DataType.Float)
.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 { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const schema = [
{
name: "age",
data_type: DataType.Int64,
},
{
name: "price",
data_type: DataType.Float,
},
{
name: "pk",
data_type: DataType.Int64,
is_primary_key: true,
},
{
name: "embedding",
data_type: DataType.FloatVector,
dim: 3,
},
];
export int64Field='{
"fieldName": "age",
"dataType": "Int64"
}'
export floatField='{
"fieldName": "price",
"dataType": "Float"
}'
export pkField='{
"fieldName": "pk",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "embedding",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 3
}
}'
export schema="{
\"autoID\": false,
\"fields\": [
$int64Field,
$floatField,
$pkField,
$vectorField
]
}"
Il campo primario e il campo vettore sono obbligatori quando si crea una collezione. Il campo primario identifica in modo univoco ogni entità, mentre il campo vettore è fondamentale per la ricerca delle somiglianze. Per maggiori dettagli, consultare Campo primario e AutoID, Vettore denso, Vettore binario o Vettore sparso.
Impostare i parametri dell'indice
L'impostazione dei parametri dell'indice per i campi numerici è facoltativa, ma può migliorare significativamente l'efficienza del recupero.
Nell'esempio seguente, si crea un AUTOINDEX
per il campo numerico age
, consentendo a Milvus di creare automaticamente un indice appropriato in base al tipo di dati. Per ulteriori informazioni, consultare AUTOINDEX.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="age",
index_type="AUTOINDEX",
index_name="inverted_index"
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
.fieldName("age")
.indexType(IndexParam.IndexType.AUTOINDEX)
.build());
const indexParams = {
index_name: 'inverted_index',
field_name: 'age',
index_type: IndexType.AUTOINDEX,
);
export indexParams='[
{
"fieldName": "age",
"indexName": "inverted_index",
"indexType": "AUTOINDEX"
}
]'
Oltre a AUTOINDEX
, è possibile specificare altri tipi di indice per i campi numerici. Per i tipi di indice supportati, fare riferimento a Indici scalari.
Inoltre, prima di creare la collezione, è necessario creare un indice per il campo vettoriale. In questo esempio, si utilizza AUTOINDEX
per semplificare le impostazioni dell'indice vettoriale.
# Add vector index
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX", # Use automatic indexing to simplify complex index settings
metric_type="COSINE" # Specify similarity metric type, options include L2, COSINE, or IP
)
indexes.add(IndexParam.builder()
.fieldName("embedding")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE)
.build());
import { IndexType } from "@zilliz/milvus2-sdk-node";
const indexParams = [
{
field_name: "age",
index_name: "inverted_index",
index_type: IndexType.AUTOINDEX,
},
{
field_name: "embedding",
metric_type: "COSINE",
index_type: IndexType.AUTOINDEX,
},
];
export indexParams='[
{
"fieldName": "age",
"indexName": "inverted_index",
"indexType": "AUTOINDEX"
},
{
"fieldName": "embedding",
"metricType": "COSINE",
"indexType": "AUTOINDEX"
}
]'
Creare la collezione
Una volta definiti lo schema e gli indici, è possibile creare una collezione che includa i campi numerici.
# Create Collection
client.create_collection(
collection_name="your_collection_name",
schema=schema,
index_params=index_params
)
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_scalar_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
client.create_collection({
collection_name: "my_scalar_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_scalar_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
Inserire i dati
Dopo aver creato la collezione, è possibile inserire i dati che includono i campi numerici.
data = [
{"age": 25, "price": 99.99, "pk": 1, "embedding": [0.1, 0.2, 0.3]},
{"age": 30, "price": 149.50, "pk": 2, "embedding": [0.4, 0.5, 0.6]},
{"age": 35, "price": 199.99, "pk": 3, "embedding": [0.7, 0.8, 0.9]},
]
client.insert(
collection_name="my_scalar_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("{\"age\": 25, \"price\": 99.99, \"pk\": 1, \"embedding\": [0.1, 0.2, 0.3]}", JsonObject.class));
rows.add(gson.fromJson("{\"age\": 30, \"price\": 149.50, \"pk\": 2, \"embedding\": [0.4, 0.5, 0.6]}", JsonObject.class));
rows.add(gson.fromJson("{\"age\": 35, \"price\": 199.99, \"pk\": 3, \"embedding\": [0.7, 0.8, 0.9]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_scalar_collection")
.data(rows)
.build());
const data = [
{ age: 25, price: 99.99, pk: 1, embedding: [0.1, 0.2, 0.3] },
{ age: 30, price: 149.5, pk: 2, embedding: [0.4, 0.5, 0.6] },
{ age: 35, price: 199.99, pk: 3, embedding: [0.7, 0.8, 0.9] },
];
client.insert({
collection_name: "my_scalar_collection",
data: data,
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"age": 25, "price": 99.99, "pk": 1, "embedding": [0.1, 0.2, 0.3]},
{"age": 30, "price": 149.50, "pk": 2, "embedding": [0.4, 0.5, 0.6]},
{"age": 35, "price": 199.99, "pk": 3, "embedding": [0.7, 0.8, 0.9]}
],
"collectionName": "my_scalar_collection"
}'
In questo esempio, si inseriscono dati che includono age
, price
, pk
(campo primario) e rappresentazioni vettoriali (embedding
). Per assicurarsi che i dati inseriti corrispondano ai campi definiti nello schema, si consiglia di controllare in anticipo i tipi di dati per evitare errori.
Se si imposta enable_dynamic_fields=True
durante la definizione dello schema, Milvus consente di inserire campi numerici non definiti in precedenza. Tuttavia, si tenga presente che ciò può aumentare la complessità delle query e della gestione, con un potenziale impatto sulle prestazioni. Per ulteriori informazioni, consultare Campo dinamico.
Ricerca e query
Dopo aver aggiunto i campi numerici, è possibile utilizzarli per il filtraggio nelle operazioni di ricerca e di interrogazione per ottenere risultati di ricerca più precisi.
Filtro delle query
Dopo aver aggiunto i campi numerici, è possibile utilizzarli per filtrare le query. Ad esempio, è possibile interrogare tutte le entità in cui age
è compreso tra 30 e 40.
filter = "30 <= age <= 40"
res = client.query(
collection_name="my_scalar_collection",
filter=filter,
output_fields=["age","price"]
)
print(res)
# Output
# data: ["{'age': 30, 'price': np.float32(149.5), 'pk': 2}", "{'age': 35, 'price': np.float32(199.99), 'pk': 3}"]
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
String filter = "30 <= age <= 40";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_scalar_collection")
.filter(filter)
.outputFields(Arrays.asList("age", "price"))
.build());
System.out.println(resp.getQueryResults());
// Output
//
// [QueryResp.QueryResult(entity={price=149.5, pk=2, age=30}), QueryResp.QueryResult(entity={price=199.99, pk=3, age=35})]
client.query({
collection_name: 'my_scalar_collection',
filter: '30 <= age <= 40',
output_fields: ['age', 'price']
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_scalar_collection",
"filter": "30 <= age <= 40",
"outputFields": ["age","price"]
}'
## {"code":0,"cost":0,"data":[{"age":30,"pk":2,"price":149.5},{"age":35,"pk":3,"price":199.99}]}
Questa espressione di query restituisce tutte le entità corrispondenti e fornisce i campi age
e price
. Per ulteriori informazioni sulle query di filtro, consultare Filtraggio dei metadati.
Ricerca vettoriale con filtraggio dei numeri
Oltre al filtraggio di base dei campi numerici, è possibile combinare la ricerca per similarità vettoriale con i filtri dei campi numerici. Ad esempio, il codice seguente mostra come aggiungere un filtro per campi numerici a una ricerca vettoriale.
filter = "25 <= age <= 35"
res = client.search(
collection_name="my_scalar_collection",
data=[[0.3, -0.6, 0.1]],
limit=5,
search_params={"params": {"nprobe": 10}},
output_fields=["age","price"],
filter=filter
)
print(res)
# Output
# data: ["[{'id': 1, 'distance': -0.06000000238418579, 'entity': {'age': 25, 'price': 99.98999786376953}}, {'id': 2, 'distance': -0.12000000476837158, 'entity': {'age': 30, 'price': 149.5}}, {'id': 3, 'distance': -0.18000000715255737, 'entity': {'age': 35, 'price': 199.99000549316406}}]"]
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;
String filter = "25 <= age <= 35";
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_scalar_collection")
.annsField("embedding")
.data(Collections.singletonList(new FloatVec(new float[]{0.3f, -0.6f, 0.1f})))
.topK(5)
.outputFields(Arrays.asList("age", "price"))
.filter(filter)
.build());
System.out.println(resp.getSearchResults());
// Output
//
// [[SearchResp.SearchResult(entity={price=199.99, age=35}, score=-0.19054288, id=3), SearchResp.SearchResult(entity={price=149.5, age=30}, score=-0.20163085, id=2), SearchResp.SearchResult(entity={price=99.99, age=25}, score=-0.2364331, id=1)]]
client.search({
collection_name: 'my_scalar_collection',
data: [0.3, -0.6, 0.1],
limit: 5,
output_fields: ['age', 'price'],
filter: '25 <= age <= 35'
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_scalar_collection",
"data": [
[0.3, -0.6, 0.1]
],
"annsField": "embedding",
"limit": 5,
"outputFields": ["age", "price"]
}'
## {"code":0,"cost":0,"data":[{"age":35,"distance":-0.19054288,"id":3,"price":199.99},{"age":30,"distance":-0.20163085,"id":2,"price":149.5},{"age":25,"distance":-0.2364331,"id":1,"price":99.99}]}
In questo esempio, si definisce prima un vettore di query e si aggiunge una condizione di filtro 25 <= age <= 35
durante la ricerca. In questo modo si garantisce che i risultati della ricerca non solo siano simili al vettore della query, ma che soddisfino anche l'intervallo di età specificato. Per ulteriori informazioni, consultare Filtraggio dei metadati.