Array von StructsCompatible with Milvus 2.6.4+
Ein Feld "Array of Structs" in einer Entität speichert eine geordnete Menge von Strukturelementen. Jede Struct im Array hat dasselbe vordefinierte Schema, das mehrere Vektoren und skalare Felder umfasst.
Hier ist ein Beispiel für eine Entität aus einer Sammlung, die ein Array of Structs-Feld enthält.
{
'id': 0,
'title': 'Walden',
'title_vector': [0.1, 0.2, 0.3, 0.4, 0.5],
'author': 'Henry David Thoreau',
'year_of_publication': 1845,
'chunks': [
{
'text': 'When I wrote the following pages, or rather the bulk of them...',
'text_vector': [0.3, 0.2, 0.3, 0.2, 0.5],
'chapter': 'Economy',
},
{
'text': 'I would fain say something, not so much concerning the Chinese and...',
'text_vector': [0.7, 0.4, 0.2, 0.7, 0.8],
'chapter': 'Economy'
}
]
// hightlight-end
}
Im obigen Beispiel ist das Feld chunks ein Array of Structs-Feld, und jedes Struct-Element enthält seine eigenen Felder, nämlich text, text_vector und chapter.
Begrenzungen
Datentypen
Wenn Sie eine Sammlung erstellen, können Sie den Typ Struct als Datentyp für die Elemente in einem Array-Feld verwenden. Sie können jedoch kein Array von Structs zu einer bestehenden Sammlung hinzufügen, und Milvus unterstützt nicht die Verwendung des Typs Struct als Datentyp für ein Sammlungsfeld.
Die Structs in einem Array-Feld haben das gleiche Schema, das beim Erstellen des Array-Feldes definiert werden sollte.
Ein Struct-Schema enthält sowohl Vektoren als auch skalare Felder, wie in der folgenden Tabelle aufgeführt:
Feldtyp
Datentyp
Vektor
FLOAT_VECTORSkalar
VARCHARINT8/16/32/64FLOATDOUBLEBOOLEANDie Anzahl der Vektorfelder sollte sowohl auf der Sammlungsebene als auch in den Structs zusammengenommen nicht größer oder gleich 10 sein.
Nullbar & Standardwerte
Ein Array of Structs-Feld ist nicht löschbar und akzeptiert keinen Standardwert.
Funktion
Sie können keine Funktion verwenden, um ein Vektorfeld aus einem Skalarfeld innerhalb einer Struktur abzuleiten.
Index-Typ & metrischer Typ
Alle Vektorfelder in einer Sammlung müssen indiziert sein. Um ein Vektorfeld innerhalb eines Array of Structs Feldes zu indizieren, verwendet Milvus eine Einbettungsliste, um die Vektoreinbettungen in jedem Struct-Element zu organisieren und indiziert die gesamte Einbettungsliste als Ganzes.
Sie können
AUTOINDEXoderHNSWals Indextyp und jeden unten aufgeführten metrischen Typ verwenden, um Indizes für die Einbettungslisten in einem Array of Structs Feld zu erstellen.Index-Typ
Metrischer Typ
Bemerkungen
AUTOINDEX(oderHNSW)MAX_SIM_COSINEFür Einbettungslisten der folgenden Typen:
- FLOAT_VECTOR
MAX_SIM_IPMAX_SIM_L2Die skalaren Felder im Feld Array of Structs unterstützen keine Indizes.
Upsert-Daten
Structs unterstützen kein Upsert im Merge-Modus. Sie können jedoch Upserts im Überschreibungsmodus durchführen, um Daten in Structs zu aktualisieren. Einzelheiten zu den Unterschieden zwischen Upsert im Zusammenführungsmodus und im Überschreibungsmodus finden Sie unter Upsert-Entitäten.
Skalare Filterung
Sie können ein Array von Structs oder Felder innerhalb seines Struct-Elements nicht in Filterausdrücken innerhalb von Suchen und Abfragen verwenden.
Array of Structs hinzufügen
Um ein Array of Structs in Milvus zu verwenden, müssen Sie beim Erstellen einer Sammlung ein Array-Feld definieren und den Datentyp für seine Elemente auf Struct setzen. Der Prozess ist wie folgt:
Setzen Sie den Datentyp eines Feldes auf
DataType.ARRAY, wenn Sie das Feld als Array-Feld zum Schema der Sammlung hinzufügen.Setzen Sie das Attribut
element_typedes Felds aufDataType.STRUCT, um das Feld zu einem Array von Structs zu machen.Erstellen Sie ein Struct-Schema und fügen Sie die erforderlichen Felder ein. Dann referenzieren Sie das Struct-Schema im Attribut
struct_schemades Feldes.Setzen Sie das Attribut
max_capacitydes Felds auf einen geeigneten Wert, um die maximale Anzahl von Structs anzugeben, die jede Entität in diesem Feld enthalten kann.(Optional) Sie können
mmap.enabledfür jedes Feld innerhalb des Struct-Elements festlegen, um die heißen und kalten Daten in der Struktur auszugleichen.
So können Sie ein Sammelschema definieren, das ein Array von Structs enthält:
from pymilvus import MilvusClient, DataType
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
schema = client.create_schema()
# add the primary field to the collection
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
# add some scalar fields to the collection
schema.add_field(field_name="title", datatype=DataType.VARCHAR, max_length=512)
schema.add_field(field_name="author", datatype=DataType.VARCHAR, max_length=512)
schema.add_field(field_name="year_of_publication", datatype=DataType.INT64)
# add a vector field to the collection
schema.add_field(field_name="title_vector", datatype=DataType.FLOAT_VECTOR, dim=5)
# Create a struct schema
struct_schema = client.create_struct_field_schema()
# add a scalar field to the struct
struct_schema.add_field("text", DataType.VARCHAR, max_length=65535)
struct_schema.add_field("chapter", DataType.VARCHAR, max_length=512)
# add a vector field to the struct with mmap enabled
struct_schema.add_field("text_vector", DataType.FLOAT_VECTOR, mmap_enabled=True, dim=5)
# reference the struct schema in an Array field with its
# element type set to `DataType.STRUCT`
schema.add_field("chunks", datatype=DataType.ARRAY, element_type=DataType.STRUCT,
struct_schema=struct_schema, max_capacity=1000)
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
.build();
collectionSchema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.autoID(true)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("title")
.dataType(DataType.VarChar)
.maxLength(512)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("author")
.dataType(DataType.VarChar)
.maxLength(512)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("year_of_publication")
.dataType(DataType.Int64)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("title_vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
Map<String, String> params = new HashMap<>();
params.put("mmap_enabled", "true");
collectionSchema.addField(AddFieldReq.builder()
.fieldName("chunks")
.dataType(DataType.Array)
.elementType(DataType.Struct)
.maxCapacity(1000)
.addStructField(AddFieldReq.builder()
.fieldName("text")
.dataType(DataType.VarChar)
.maxLength(65535)
.build())
.addStructField(AddFieldReq.builder()
.fieldName("chapter")
.dataType(DataType.VarChar)
.maxLength(512)
.build())
.addStructField(AddFieldReq.builder()
.fieldName("text_vector")
.dataType(DataType.FloatVector)
.dimension(VECTOR_DIM)
.typeParams(params)
.build())
.build());
// go
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const milvusClient = new MilvusClient("http://localhost:19530");
const schema = [
{
name: "id",
data_type: DataType.INT64,
is_primary_key: true,
auto_id: true,
},
{
name: "title",
data_type: DataType.VARCHAR,
max_length: 512,
},
{
name: "author",
data_type: DataType.VARCHAR,
max_length: 512,
},
{
name: "year_of_publication",
data_type: DataType.INT64,
},
{
name: "title_vector",
data_type: DataType.FLOAT_VECTOR,
dim: 5,
},
{
name: "chunks",
data_type: DataType.ARRAY,
element_type: DataType.STRUCT,
fields: [
{
name: "text",
data_type: DataType.VARCHAR,
max_length: 65535,
},
{
name: "chapter",
data_type: DataType.VARCHAR,
max_length: 512,
},
{
name: "text_vector",
data_type: DataType.FLOAT_VECTOR,
dim: 5,
mmap_enabled: true,
},
],
max_capacity: 1000,
},
];
# restful
SCHEMA='{
"autoID": true,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
},
{
"fieldName": "title",
"dataType": "VarChar",
"elementTypeParams": { "max_length": "512" }
},
{
"fieldName": "author",
"dataType": "VarChar",
"elementTypeParams": { "max_length": "512" }
},
{
"fieldName": "year_of_publication",
"dataType": "Int64"
},
{
"fieldName": "title_vector",
"dataType": "FloatVector",
"elementTypeParams": { "dim": "5" }
}
],
"structArrayFields": [
{
"name": "chunks",
"description": "Array of document chunks with text and vectors",
"elementTypeParams":{
"max_capacity": 1000
},
"fields": [
{
"fieldName": "text",
"dataType": "VarChar",
"elementTypeParams": { "max_length": "65535" }
},
{
"fieldName": "chapter",
"dataType": "VarChar",
"elementTypeParams": { "max_length": "512" }
},
{
"fieldName": "text_vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": "5",
"mmap_enabled": "true"
}
}
]
}
]
}'
Die hervorgehobenen Zeilen im obigen Codebeispiel veranschaulichen das Verfahren zur Aufnahme eines Arrays von Structs in ein Auflistungsschema.
Index-Parameter setzen
Die Indexierung ist für alle Vektorfelder obligatorisch, sowohl für die Vektorfelder in der Sammlung als auch für die im Element Struct definierten.
Die anwendbaren Indexparameter variieren je nach verwendetem Indextyp. Einzelheiten zu den anwendbaren Indexparametern finden Sie unter Index erklärt und auf den Dokumentationsseiten, die für den von Ihnen gewählten Indextyp spezifisch sind.
Um eine Einbettungsliste zu indizieren, müssen Sie ihren Indextyp auf AUTOINDEX oder HNSW setzen und MAX_SIM_COSINE als metrischen Typ für Milvus verwenden, um die Ähnlichkeiten zwischen Einbettungslisten zu messen.
# Create index parameters
index_params = client.prepare_index_params()
# Create an index for the vector field in the collection
index_params.add_index(
field_name="title_vector",
index_type="AUTOINDEX",
metric_type="L2",
)
# Create an index for the vector field in the element Struct
index_params.add_index(
field_name="chunks[text_vector]",
index_type="AUTOINDEX",
metric_type="MAX_SIM_COSINE",
)
import io.milvus.v2.common.IndexParam;
List<IndexParam> indexParams = new ArrayList<>();
indexParams.add(IndexParam.builder()
.fieldName("title_vector")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.L2)
.build());
indexParams.add(IndexParam.builder()
.fieldName("chunks[text_vector]")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.MAX_SIM_COSINE)
.build());
// go
await milvusClient.createCollection({
collection_name: "books",
fields: schema,
});
const indexParams = [
{
field_name: "title_vector",
index_type: "AUTOINDEX",
metric_type: "L2",
},
{
field_name: "chunks[text_vector]",
index_type: "AUTOINDEX",
metric_type: "MAX_SIM_COSINE",
},
];
# restful
INDEX_PARAMS='[
{
"fieldName": "title_vector",
"indexName": "title_vector_index",
"indexType": "AUTOINDEX",
"metricType": "L2"
},
{
"fieldName": "chunks[text_vector]",
"indexName": "chunks_text_vector_index",
"indexType": "AUTOINDEX",
"metricType": "MAX_SIM_COSINE"
}
]'
Erstellen Sie eine Sammlung
Sobald das Schema und der Index fertig sind, können Sie eine Sammlung erstellen, die ein Feld Array of Structs enthält.
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.token("root:Milvus")
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(collectionSchema)
.indexParams(indexParams)
.build();
client.createCollection(requestCreate);
// go
await milvusClient.createCollection({
collection_name: "books",
fields: schema,
indexes: indexParams,
});
# restful
curl -X POST "http://localhost:19530/v2/vectordb/collections/create" \
-H "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"description\": \"A collection for storing book information with struct array chunks\",
\"schema\": $SCHEMA,
\"indexParams\": $INDEX_PARAMS
}"
Daten einfügen
Nachdem Sie die Sammlung erstellt haben, können Sie wie folgt Daten einfügen, die Arrays of Structs enthalten.
# Sample data
data = {
'title': 'Walden',
'title_vector': [0.1, 0.2, 0.3, 0.4, 0.5],
'author': 'Henry David Thoreau',
'year_of_publication': 1845,
'chunks': [
{
'text': 'When I wrote the following pages, or rather the bulk of them...',
'text_vector': [0.3, 0.2, 0.3, 0.2, 0.5],
'chapter': 'Economy',
},
{
'text': 'I would fain say something, not so much concerning the Chinese and...',
'text_vector': [0.7, 0.4, 0.2, 0.7, 0.8],
'chapter': 'Economy'
}
]
}
# insert data
client.insert(
collection_name="my_collection",
data=[data]
)
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
Gson gson = new Gson();
JsonObject row = new JsonObject();
row.addProperty("title", "Walden");
row.add("title_vector", gson.toJsonTree(Arrays.asList(0.1f, 0.2f, 0.3f, 0.4f, 0.5f)));
row.addProperty("author", "Henry David Thoreau");
row.addProperty("year_of_publication", 1845);
JsonArray structArr = new JsonArray();
JsonObject struct1 = new JsonObject();
struct1.addProperty("text", "When I wrote the following pages, or rather the bulk of them...");
struct1.add("text_vector", gson.toJsonTree(Arrays.asList(0.3f, 0.2f, 0.3f, 0.2f, 0.5f)));
struct1.addProperty("chapter", "Economy");
structArr.add(struct1);
JsonObject struct2 = new JsonObject();
struct2.addProperty("text", "I would fain say something, not so much concerning the Chinese and...");
struct2.add("text_vector", gson.toJsonTree(Arrays.asList(0.7f, 0.4f, 0.2f, 0.7f, 0.8f)));
struct2.addProperty("chapter", "Economy");
structArr.add(struct2);
row.add("chunks", structArr);
InsertResp insertResp = client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(row))
.build());
// go
{
id: 0,
title: "Walden",
title_vector: [0.1, 0.2, 0.3, 0.4, 0.5],
author: "Henry David Thoreau",
"year-of-publication": 1845,
chunks: [
{
text: "When I wrote the following pages, or rather the bulk of them...",
text_vector: [0.3, 0.2, 0.3, 0.2, 0.5],
chapter: "Economy",
},
{
text: "I would fain say something, not so much concerning the Chinese and...",
text_vector: [0.7, 0.4, 0.2, 0.7, 0.8],
chapter: "Economy",
},
],
},
];
await milvusClient.insert({
collection_name: "books",
data: data,
});
# restful
curl -X POST "http://localhost:19530/v2/vectordb/entities/insert" \
-H "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"data": [
{
"title": "Walden",
"title_vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"author": "Henry David Thoreau",
"year_of_publication": 1845,
"chunks": [
{
"text": "When I wrote the following pages, or rather the bulk of them...",
"text_vector": [0.3, 0.2, 0.3, 0.2, 0.5],
"chapter": "Economy"
},
{
"text": "I would fain say something, not so much concerning the Chinese and...",
"text_vector": [0.7, 0.4, 0.2, 0.7, 0.8],
"chapter": "Economy"
}
]
}
]
}'
import json
import random
from typing import List, Dict, Any
# Real classic books (title, author, year)
BOOKS = [
("Pride and Prejudice", "Jane Austen", 1813),
("Moby Dick", "Herman Melville", 1851),
("Frankenstein", "Mary Shelley", 1818),
("The Picture of Dorian Gray", "Oscar Wilde", 1890),
("Dracula", "Bram Stoker", 1897),
("The Adventures of Sherlock Holmes", "Arthur Conan Doyle", 1892),
("Alice's Adventures in Wonderland", "Lewis Carroll", 1865),
("The Time Machine", "H.G. Wells", 1895),
("The Scarlet Letter", "Nathaniel Hawthorne", 1850),
("Leaves of Grass", "Walt Whitman", 1855),
("The Brothers Karamazov", "Fyodor Dostoevsky", 1880),
("Crime and Punishment", "Fyodor Dostoevsky", 1866),
("Anna Karenina", "Leo Tolstoy", 1877),
("War and Peace", "Leo Tolstoy", 1869),
("Great Expectations", "Charles Dickens", 1861),
("Oliver Twist", "Charles Dickens", 1837),
("Wuthering Heights", "Emily Brontë", 1847),
("Jane Eyre", "Charlotte Brontë", 1847),
("The Call of the Wild", "Jack London", 1903),
("The Jungle Book", "Rudyard Kipling", 1894),
]
# Common chapter names for classics
CHAPTERS = [
"Introduction", "Prologue", "Chapter I", "Chapter II", "Chapter III",
"Chapter IV", "Chapter V", "Chapter VI", "Chapter VII", "Chapter VIII",
"Chapter IX", "Chapter X", "Epilogue", "Conclusion", "Afterword",
"Economy", "Where I Lived", "Reading", "Sounds", "Solitude",
"Visitors", "The Bean-Field", "The Village", "The Ponds", "Baker Farm"
]
# Placeholder text snippets (mimicking 19th-century prose)
TEXT_SNIPPETS = [
"When I wrote the following pages, or rather the bulk of them...",
"I would fain say something, not so much concerning the Chinese and...",
"It is a truth universally acknowledged, that a single man in possession...",
"Call me Ishmael. Some years ago—never mind how long precisely...",
"It was the best of times, it was the worst of times...",
"All happy families are alike; each unhappy family is unhappy in its own way.",
"Whether I shall turn out to be the hero of my own life, or whether that station...",
"You will rejoice to hear that no disaster has accompanied the commencement...",
"The world is too much with us; late and soon, getting and spending...",
"He was an old man who fished alone in a skiff in the Gulf Stream..."
]
def random_vector() -> List[float]:
return [round(random.random(), 1) for _ in range(5)]
def generate_chunk() -> Dict[str, Any]:
return {
"text": random.choice(TEXT_SNIPPETS),
"text_vector": random_vector(),
"chapter": random.choice(CHAPTERS)
}
def generate_record(record_id: int) -> Dict[str, Any]:
title, author, year = random.choice(BOOKS)
num_chunks = random.randint(1, 5) # 1 to 5 chunks per book
chunks = [generate_chunk() for _ in range(num_chunks)]
return {
"title": title,
"title_vector": random_vector(),
"author": author,
"year_of_publication": year,
"chunks": chunks
}
# Generate 1000 records
data = [generate_record(i) for i in range(1000)]
# Insert the generated data
client.insert(collection_name="my_collection", data=data)
Vektorsuche in einem Array of Structs-Feld
Sie können Vektorsuchen in den Vektorfeldern einer Sammlung und in einem Array of Structs durchführen.
Insbesondere sollten Sie den Namen des Array of Structs-Feldes und die der Zielvektorfelder innerhalb der Struct-Elemente als Wert für den anns_field -Parameter in einer Suchanfrage verketten und EmbeddingList verwenden, um Abfragevektoren ordentlich zu organisieren.
Milvus bietet EmbeddingList, um Ihnen zu helfen, Abfragevektoren für Suchen gegen eine Einbettungsliste in einem Array of Structs ordentlicher zu organisieren. Jede EmbeddingList enthält mindestens eine Vektoreinbettung und erwartet im Gegenzug eine Anzahl von topK Entitäten.
Allerdings kann EmbeddingList nur in search() Anfragen ohne Bereichssuche oder gruppierende Suchparameter verwendet werden, geschweige denn in search_iterator() Anfragen.
from pymilvus.client.embedding_list import EmbeddingList
# each query embedding list triggers a single search
embeddingList1 = EmbeddingList()
embeddingList1.add([0.2, 0.9, 0.4, -0.3, 0.2])
embeddingList2 = EmbeddingList()
embeddingList2.add([-0.2, -0.2, 0.5, 0.6, 0.9])
embeddingList2.add([-0.4, 0.3, 0.5, 0.8, 0.2])
# a search with a single embedding list
results = client.search(
collection_name="my_collection",
data=[ embeddingList1 ],
anns_field="chunks[text_vector]",
search_params={"metric_type": "MAX_SIM_COSINE"},
limit=3,
output_fields=["chunks[text]"]
)
import io.milvus.v2.service.vector.request.data.EmbeddingList;
import io.milvus.v2.service.vector.request.data.FloatVec;
EmbeddingList embeddingList1 = new EmbeddingList();
embeddingList1.add(new FloatVec(new float[]{0.2f, 0.9f, 0.4f, -0.3f, 0.2f}));
EmbeddingList embeddingList2 = new EmbeddingList();
embeddingList2.add(new FloatVec(new float[]{-0.2f, -0.2f, 0.5f, 0.6f, 0.9f}));
embeddingList2.add(new FloatVec(new float[]{-0.4f, 0.3f, 0.5f, 0.8f, 0.2f}));
Map<String, Object> params = new HashMap<>();
params.put("metric_type", "MAX_SIM_COSINE");
SearchResp searchResp = client.search(SearchReq.builder()
.collectionName("my_collection")
.annsField("chunks[text_vector]")
.data(Collections.singletonList(embeddingList1))
.searchParams(params)
.limit(3)
.outputFields(Collections.singletonList("chunks[text]"))
.build());
// go
const embeddingList1 = [[0.2, 0.9, 0.4, -0.3, 0.2]];
const embeddingList2 = [
[-0.2, -0.2, 0.5, 0.6, 0.9],
[-0.4, 0.3, 0.5, 0.8, 0.2],
];
const results = await milvusClient.search({
collection_name: "books",
data: embeddingList1,
anns_field: "chunks[text_vector]",
search_params: { metric_type: "MAX_SIM_COSINE" },
limit: 3,
output_fields: ["chunks[text]"],
});
# restful
embeddingList1='[[0.2,0.9,0.4,-0.3,0.2]]'
embeddingList2='[[-0.2,-0.2,0.5,0.6,0.9],[-0.4,0.3,0.5,0.8,0.2]]'
curl -X POST "http://localhost:19530/v2/vectordb/entities/search" \
-H "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"data\": [$embeddingList1],
\"annsField\": \"chunks[text_vector]\",
\"searchParams\": {\"metric_type\": \"MAX_SIM_COSINE\"},
\"limit\": 3,
\"outputFields\": [\"chunks[text]\"]
}"
Die obige Suchanfrage verwendet chunks[text_vector], um auf das Feld text_vector in Struct-Elementen zu verweisen. Sie können diese Syntax verwenden, um die Parameter anns_field und output_fields zu setzen.
Die Ausgabe wäre eine Liste mit den drei ähnlichsten Entitäten.
# [
# [
# {
# 'id': 461417939772144945,
# 'distance': 0.9675756096839905,
# 'entity': {
# 'chunks': [
# {'text': 'The world is too much with us; late and soon, getting and spending...'},
# {'text': 'All happy families are alike; each unhappy family is unhappy in its own way.'}
# ]
# }
# },
# {
# 'id': 461417939772144965,
# 'distance': 0.9555778503417969,
# 'entity': {
# 'chunks': [
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'},
# {'text': 'He was an old man who fished alone in a skiff in the Gulf Stream...'},
# {'text': 'When I wrote the following pages, or rather the bulk of them...'},
# {'text': 'It was the best of times, it was the worst of times...'},
# {'text': 'The world is too much with us; late and soon, getting and spending...'}
# ]
# }
# },
# {
# 'id': 461417939772144962,
# 'distance': 0.9469035863876343,
# 'entity': {
# 'chunks': [
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'},
# {'text': 'The world is too much with us; late and soon, getting and spending...'},
# {'text': 'He was an old man who fished alone in a skiff in the Gulf Stream...'},
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'},
# {'text': 'The world is too much with us; late and soon, getting and spending...'}
# ]
# }
# }
# ]
# ]
Sie können auch mehrere Einbettungslisten in den Parameter data aufnehmen, um Suchergebnisse für jede dieser Einbettungslisten abzurufen.
# a search with multiple embedding lists
results = client.search(
collection_name="my_collection",
data=[ embeddingList1, embeddingList2 ],
anns_field="chunks[text_vector]",
search_params={"metric_type": "MAX_SIM_COSINE"},
limit=3,
output_fields=["chunks[text]"]
)
print(results)
Map<String, Object> params = new HashMap<>();
params.put("metric_type", "MAX_SIM_COSINE");
SearchResp searchResp = client.search(SearchReq.builder()
.collectionName("my_collection")
.annsField("chunks[text_vector]")
.data(Arrays.asList(embeddingList1, embeddingList2))
.searchParams(params)
.limit(3)
.outputFields(Collections.singletonList("chunks[text]"))
.build());
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (int i = 0; i < searchResults.size(); i++) {
System.out.println("Results of No." + i + " embedding list");
List<SearchResp.SearchResult> results = searchResults.get(i);
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// go
const results2 = await milvusClient.search({
collection_name: "books",
data: [embeddingList1, embeddingList2],
anns_field: "chunks[text_vector]",
search_params: { metric_type: "MAX_SIM_COSINE" },
limit: 3,
output_fields: ["chunks[text]"],
});
# restful
curl -X POST "http://localhost:19530/v2/vectordb/entities/search" \
-H "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"data\": [$embeddingList1, $embeddingList2],
\"annsField\": \"chunks[text_vector]\",
\"searchParams\": {\"metric_type\": \"MAX_SIM_COSINE\"},
\"limit\": 3,
\"outputFields\": [\"chunks[text]\"]
}"
Die Ausgabe wäre eine Liste mit den drei ähnlichsten Entitäten für jede Einbettungsliste.
# [
# [
# {
# 'id': 461417939772144945,
# 'distance': 0.9675756096839905,
# 'entity': {
# 'chunks': [
# {'text': 'The world is too much with us; late and soon, getting and spending...'},
# {'text': 'All happy families are alike; each unhappy family is unhappy in its own way.'}
# ]
# }
# },
# {
# 'id': 461417939772144965,
# 'distance': 0.9555778503417969,
# 'entity': {
# 'chunks': [
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'},
# {'text': 'He was an old man who fished alone in a skiff in the Gulf Stream...'},
# {'text': 'When I wrote the following pages, or rather the bulk of them...'},
# {'text': 'It was the best of times, it was the worst of times...'},
# {'text': 'The world is too much with us; late and soon, getting and spending...'}
# ]
# }
# },
# {
# 'id': 461417939772144962,
# 'distance': 0.9469035863876343,
# 'entity': {
# 'chunks': [
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'},
# {'text': 'The world is too much with us; late and soon, getting and spending...'},
# {'text': 'He was an old man who fished alone in a skiff in the Gulf Stream...'},
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'},
# {'text': 'The world is too much with us; late and soon, getting and spending...'}
# ]
# }
# }
# ],
# [
# {
# 'id': 461417939772144663,
# 'distance': 1.9761409759521484,
# 'entity': {
# 'chunks': [
# {'text': 'It was the best of times, it was the worst of times...'},
# {'text': 'It is a truth universally acknowledged, that a single man in possession...'},
# {'text': 'Whether I shall turn out to be the hero of my own life, or whether that station...'},
# {'text': 'He was an old man who fished alone in a skiff in the Gulf Stream...'}
# ]
# }
# },
# {
# 'id': 461417939772144692,
# 'distance': 1.974656581878662,
# 'entity': {
# 'chunks': [
# {'text': 'It is a truth universally acknowledged, that a single man in possession...'},
# {'text': 'Call me Ishmael. Some years ago—never mind how long precisely...'}
# ]
# }
# },
# {
# 'id': 461417939772144662,
# 'distance': 1.9406685829162598,
# 'entity': {
# 'chunks': [
# {'text': 'It is a truth universally acknowledged, that a single man in possession...'}
# ]
# }
# }
# ]
# ]
Im obigen Codebeispiel ist embeddingList1 eine Einbettungsliste mit einem Vektor, während embeddingList2 zwei Vektoren enthält. Jeder löst eine separate Suchanfrage aus und erwartet eine Liste der K ähnlichsten Entitäten.
Nächste Schritte
Die Entwicklung eines nativen Array of Structs-Datentyps stellt einen großen Fortschritt in der Fähigkeit von Milvus dar, komplexe Datenstrukturen zu verarbeiten. Um die Anwendungsfälle besser zu verstehen und diese neue Funktion optimal zu nutzen, sollten Sie Schema Design Using an Array of Structs lesen.