Zahlenfeld
Zahlenfelder werden verwendet, um nicht-vektorielle numerische Daten in Milvus zu speichern. Diese Felder werden in der Regel verwendet, um zusätzliche Informationen in Bezug auf Vektordaten zu beschreiben, z. B. Alter, Preis usw. Durch die Verwendung dieser Daten können Sie Vektoren besser beschreiben und die Effizienz der Datenfilterung und bedingter Abfragen verbessern.
Zahlenfelder sind in vielen Szenarien besonders nützlich. So kann beispielsweise bei E-Commerce-Empfehlungen ein Preisfeld zur Filterung verwendet werden; bei der Analyse von Benutzerprofilen können Altersbereiche zur Verfeinerung der Ergebnisse beitragen. In Kombination mit Vektordaten können Zahlenfelder dazu beitragen, dass das System Ähnlichkeitssuchen anbietet und gleichzeitig die Bedürfnisse der Benutzer genauer erfüllt.
Unterstützte Zahlenfeldtypen
Milvus unterstützt verschiedene Zahlenfeldtypen, um unterschiedliche Anforderungen an die Datenspeicherung und Abfrage zu erfüllen.
Typ | Beschreibung |
---|---|
| Boolescher Typ zur Speicherung von |
| 8-Bit-Ganzzahl, geeignet für die Speicherung von Ganzzahldaten mit kleinem Bereich. |
| 16-Bit-Integer, für Integer-Daten mittlerer Reichweite. |
| 32-Bit-Ganzzahl, ideal für die Speicherung allgemeiner Ganzzahldaten wie Produktmengen oder Benutzer-IDs. |
| 64-Bit-Ganzzahl, geeignet für die Speicherung großer Datenmengen wie Zeitstempel oder Kennungen. |
| 32-Bit-Gleitkommazahl, für Daten, die eine allgemeine Genauigkeit erfordern, wie z. B. Bewertungen oder Temperaturen. |
| 64-Bit-Gleitkommazahl mit doppelter Genauigkeit, für hochpräzise Daten wie Finanzinformationen oder wissenschaftliche Berechnungen. |
Zahlenfeld hinzufügen
Um Zahlenfelder in Milvus zu verwenden, definieren Sie die entsprechenden Felder im Sammlungsschema, indem Sie die datatype
auf einen unterstützten Typ wie BOOL
oder INT8
setzen. Eine vollständige Liste der unterstützten Zahlenfeldtypen finden Sie unter Unterstützte Zahlenfeldtypen.
Das folgende Beispiel zeigt, wie Sie ein Schema definieren, das die Zahlenfelder age
und price
enthält.
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
]
}"
Das Primärfeld und das Vektorfeld sind obligatorisch, wenn Sie eine Sammlung erstellen. Das Primärfeld identifiziert jede Entität eindeutig, während das Vektorfeld für die Ähnlichkeitssuche entscheidend ist. Weitere Einzelheiten finden Sie unter Primärfeld & AutoID, Dense Vector, Binary Vector oder Sparse Vector.
Index-Parameter setzen
Das Setzen von Indexparametern für Zahlenfelder ist optional, kann aber die Abfrageeffizienz erheblich verbessern.
Im folgenden Beispiel erstellen wir eine AUTOINDEX
für das Zahlenfeld age
, so dass Milvus automatisch einen geeigneten Index auf der Grundlage des Datentyps erstellen kann. Weitere Informationen finden Sie unter 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"
}
]'
Zusätzlich zu AUTOINDEX
können Sie andere Index-Typen für Zahlenfelder angeben. Informationen zu unterstützten Indextypen finden Sie unter Skalare Indizes.
Außerdem müssen Sie vor der Erstellung der Sammlung einen Index für das Vektorfeld erstellen. In diesem Beispiel verwenden wir AUTOINDEX
, um die Einstellungen für den Vektorindex zu vereinfachen.
# 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"
}
]'
Sammlung erstellen
Sobald das Schema und die Indizes definiert sind, können Sie eine Sammlung erstellen, die Zahlenfelder enthält.
# 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
}"
Daten einfügen
Nachdem Sie die Sammlung erstellt haben, können Sie Daten mit Zahlenfeldern einfügen.
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 diesem Beispiel fügen wir Daten ein, die age
, price
, pk
(Primärfeld) und Vektordarstellungen (embedding
) enthalten. Um sicherzustellen, dass die eingefügten Daten mit den im Schema definierten Feldern übereinstimmen, empfiehlt es sich, die Datentypen im Voraus zu überprüfen, um Fehler zu vermeiden.
Wenn Sie bei der Definition des Schemas enable_dynamic_fields=True
einstellen, können Sie mit Milvus auch Zahlenfelder einfügen, die nicht im Voraus definiert wurden. Beachten Sie jedoch, dass dies die Komplexität von Abfragen und Verwaltung erhöhen kann, was sich möglicherweise auf die Leistung auswirkt. Weitere Informationen finden Sie unter Dynamisches Feld.
Suche und Abfrage
Nachdem Sie Zahlenfelder hinzugefügt haben, können Sie diese zum Filtern in Such- und Abfrageoperationen verwenden, um präzisere Suchergebnisse zu erzielen.
Filterabfragen
Nachdem Sie Zahlenfelder hinzugefügt haben, können Sie diese zum Filtern in Abfragen verwenden. Zum Beispiel können Sie alle Entitäten abfragen, bei denen age
zwischen 30 und 40 liegt.
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}]}
Dieser Abfrageausdruck gibt alle übereinstimmenden Entitäten zurück und gibt deren Felder age
und price
aus. Weitere Informationen zu Filterabfragen finden Sie unter Metadatenfilterung.
Vektorsuche mit Zahlenfilterung
Zusätzlich zur grundlegenden Zahlenfeldfilterung können Sie Vektorähnlichkeitssuchen mit Zahlenfeldfiltern kombinieren. Der folgende Code zeigt zum Beispiel, wie man einen Zahlenfeldfilter zu einer Vektorsuche hinzufügt.
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 diesem Beispiel definieren wir zunächst einen Abfragevektor und fügen während der Suche eine Filterbedingung 25 <= age <= 35
hinzu. Dadurch wird sichergestellt, dass die Suchergebnisse nicht nur dem Abfragevektor ähneln, sondern auch dem angegebenen Altersbereich entsprechen. Weitere Informationen finden Sie unter Metadatenfilterung.