milvus-logo
LFAI
Home
  • Guia do utilizador

Campo numérico

Os campos numéricos são utilizados para armazenar dados numéricos não vectoriais em Milvus. Estes campos são normalmente utilizados para descrever informações adicionais relacionadas com dados vectoriais, como a idade, o preço, etc. Ao utilizar estes dados, é possível descrever melhor os vectores e melhorar a eficiência da filtragem de dados e das consultas condicionais.

Os campos numéricos são particularmente úteis em muitos cenários. Por exemplo, nas recomendações de comércio eletrónico, um campo de preço pode ser utilizado para filtragem; na análise do perfil do utilizador, os intervalos de idade podem ajudar a refinar os resultados. Combinados com dados vectoriais, os campos numéricos podem ajudar o sistema a fornecer pesquisas semelhantes, satisfazendo com maior precisão as necessidades personalizadas dos utilizadores.

Tipos de campos numéricos suportados

O Milvus suporta vários tipos de campos numéricos para satisfazer diferentes necessidades de armazenamento de dados e de consulta.

Tipo

Descrição

BOOL

Tipo booleano para armazenar true ou false, adequado para descrever estados binários.

INT8

Inteiro de 8 bits, adequado para armazenar dados inteiros de pequena dimensão.

INT16

Inteiro de 16 bits, para dados inteiros de gama média.

INT32

Inteiro de 32 bits, ideal para armazenamento de dados inteiros gerais, como quantidades de produtos ou IDs de utilizadores.

INT64

Número inteiro de 64 bits, adequado para armazenar dados de grande alcance, como carimbos de data/hora ou identificadores.

FLOAT

Número de vírgula flutuante de 32 bits, para dados que requerem precisão geral, como classificações ou temperatura.

DOUBLE

Número de vírgula flutuante de dupla precisão de 64 bits, para dados de alta precisão, como informações financeiras ou cálculos científicos.

Adicionar um campo numérico

Para utilizar campos numéricos no Milvus, defina os campos relevantes no esquema da coleção, definindo o datatype para um tipo suportado, como BOOL ou INT8. Para obter uma lista completa dos tipos de campos numéricos suportados, consulte Tipos de campos numéricos suportados.

O exemplo seguinte mostra como definir um esquema que inclui campos numéricos 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
    ]
}"

O campo primário e o campo vetorial são obrigatórios quando se cria uma coleção. O campo primário identifica exclusivamente cada entidade, enquanto o campo vetorial é crucial para a pesquisa por semelhança. Para obter mais detalhes, consulte Campo primário e AutoID, Vetor denso, Vetor binário ou Vetor esparso.

Definir parâmetros de índice

A definição de parâmetros de índice para campos numéricos é opcional, mas pode melhorar significativamente a eficiência da recuperação.

No exemplo seguinte, criamos um AUTOINDEX para o campo de número age, permitindo que o Milvus crie automaticamente um índice apropriado com base no tipo de dados. Para obter mais informações, consulte 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"
        }
    ]'

Para além de AUTOINDEX, pode especificar outros tipos de índice de campo numérico. Para obter os tipos de índice suportados, consulte Índices escalares.

Além disso, antes de criar a coleção, tem de criar um índice para o campo vetorial. Neste exemplo, utilizamos AUTOINDEX para simplificar as definições de índice de vetor.

# 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"
        }
    ]'

Criar coleção

Assim que o esquema e os índices estiverem definidos, pode criar uma coleção que inclua campos numéricos.

# 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
}"

Inserir dados

Depois de criar a coleção, pode inserir dados que incluam campos numéricos.

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"
}'

Neste exemplo, inserimos dados que incluem age, price, pk (campo primário) e representações vectoriais (embedding). Para garantir que os dados inseridos correspondem aos campos definidos no esquema, recomenda-se a verificação prévia dos tipos de dados para evitar erros.

Se definir enable_dynamic_fields=True aquando da definição do esquema, o Milvus permite-lhe inserir campos numéricos que não foram previamente definidos. No entanto, tenha em conta que isto pode aumentar a complexidade das consultas e da gestão, afectando potencialmente o desempenho. Para mais informações, consulte Campo dinâmico.

Pesquisa e consulta

Depois de adicionar campos numéricos, pode utilizá-los para filtragem em operações de pesquisa e consulta para obter resultados de pesquisa mais precisos.

Filtrar consultas

Depois de adicionar campos numéricos, pode utilizá-los para filtragem em consultas. Por exemplo, pode consultar todas as entidades em que age está entre 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}]}

Essa expressão de consulta retorna todas as entidades correspondentes e produz seus campos age e price. Para obter mais informações sobre consultas de filtro, consulte Filtragem de metadados.

Pesquisa vetorial com filtragem de números

Além da filtragem básica de campo numérico, é possível combinar pesquisas de similaridade de vetor com filtros de campo numérico. Por exemplo, o código a seguir mostra como adicionar um filtro de campo numérico a uma pesquisa de vetor.

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}]}

Neste exemplo, primeiro definimos um vetor de consulta e adicionamos uma condição de filtro 25 <= age <= 35 durante a pesquisa. Isso garante que os resultados da pesquisa não sejam apenas semelhantes ao vetor de consulta, mas também atendam à faixa etária especificada. Para obter mais informações, consulte Filtragem de metadados.

Traduzido porDeepL

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

Esta página foi útil?