Elasticsearch 查詢至 Milvus
建立在 Apache Lucene 上的 Elasticsearch 是領先的開放原始碼搜尋引擎。然而,它在現代人工智能應用程式中面臨挑戰,包括更新成本高、即時效能差、分片管理效率低、非雲原生設計,以及資源需求過高。身為雲端原生向量資料庫,Milvus 透過解耦儲存與運算、高維資料的有效索引,以及與現代基礎架構的無縫整合,克服了這些問題。它可為人工智能工作負載提供優異的效能與擴充性。
本文旨在協助您將程式碼從 Elasticsearch 遷移到 Milvus,並提供各種轉換查詢的範例。
概述
在 Elasticsearch 中,查詢上下文中的操作會產生相關性分數,而過濾上下文中的操作則不會。同樣地,Milvus 的搜尋會產生相似性分數,而類似過濾器的查詢則不會。當您的程式碼從 Elasticsearch 移轉到 Milvus 時,關鍵原則是將 Elasticsearch 的查詢上下文中使用的欄位轉換成向量欄位,以便產生相似性分數。
下表概述了一些 Elasticsearch 查詢模式及其在 Milvus 中的對應等值。
Elasticsearch 查詢 |
Milvus 對應模式 |
備註 |
|---|---|---|
全文查詢 |
||
全文檢索 |
兩者提供類似的功能。 |
|
詞彙層級查詢 |
||
|
當這些 Elasticsearch 查詢用於篩選器上下文時,兩者都提供相同或類似的功能集。 |
|
|
||
比較運算符如 |
||
比較運算符如 |
||
|
||
|
||
邏輯運算符如 |
在篩選器上下文中使用時,兩者都提供類似的功能。 |
|
向量查詢 |
||
搜尋 |
Milvus 提供更先進的向量搜尋功能。 |
|
混合搜尋 |
Milvus 支援多種重排策略。 |
|
全文本查詢
在 Elasticsearch 中,全文查詢可讓您搜尋經分析的文字欄位,例如電子郵件的正文。查詢字串會使用索引期間套用於欄位的相同分析器來處理。
匹配查詢
在 Elasticsearch 中,匹配查詢會返回符合所提供的文字、數字、日期或布林值的文件。在匹配之前,會先分析所提供的文字。
以下是一個使用匹配查詢的 Elasticsearch 搜尋請求範例。
resp = client.search(
query={
"match": {
"message": {
"query": "this is a test"
}
}
},
)
Milvus 透過全文搜尋功能提供相同的功能。您可以如下將上述 Elasticsearch 查詢轉換成 Milvus:
res = client.search(
collection_name="my_collection",
data=['How is the weather in Jamaica?'],
anns_field="message_sparse",
output_fields=["id", "message"]
)
在上面的範例中,message_sparse 是一個由 VarChar 欄位衍生出來的稀疏向量欄位,其名稱為message 。Milvus 使用 BM25 嵌入模型將message 欄位中的值轉換為稀疏向量嵌入,並儲存在message_sparse 欄位中。收到搜尋請求後,Milvus 會使用相同的 BM25 模型嵌入純文字查詢有效載荷,並執行稀疏向量搜尋,然後傳回output_fields 參數中指定的id 和message 欄位,以及相應的相似性分數。
若要使用此功能,您必須啟用message 欄位的分析器,並定義一個函式,從中得出message_sparse 欄位。有關啟用分析器和在 Milvus 中建立衍生函數的詳細說明,請參閱全文檢索。
詞彙層級查詢
在 Elasticsearch 中,詞彙層級查詢用於根據結構化資料中的精確值來尋找文件,例如日期範圍、IP 位址、價格或產品 ID。本節將介紹一些 Elasticsearch 詞彙層級查詢在 Milvus 中的可能等效方式。本節中的所有範例都經過調整,以便在篩選器上下文中運作,以符合 Milvus 的功能。
ID
在 Elasticsearch 中,您可以根據篩選上下文中的 ID 來尋找文件,如下所示:
resp = client.search(
query={
"bool": {
"filter": {
"ids": {
"values": [
"1",
"4",
"100"
]
}
}
}
},
)
在 Milvus 中,您也可以根據 ID 來尋找實體,如下所示:
# Use the filter parameter
res = client.query(
collection_name="my_collection",
filter="id in [1, 4, 100]",
output_fields=["id", "title"]
)
# Use the ids parameter
res = client.query(
collection_name="my_collection",
ids=[1, 4, 100],
output_fields=["id", "title"]
)
您可以在此頁面找到 Elasticsearch 的範例。有關查詢和獲取請求以及 Milvus 中過濾器表達式的詳細資訊,請參閱查詢和過濾。
前綴查詢
在 Elasticsearch 中,您可以在篩選上下文中找到在所提供欄位中包含特定前綴的文件,如下所示:
resp = client.search(
query={
"bool": {
"filter": {
"prefix": {
"user": {
"value": "ki"
}
}
}
}
},
)
在 Milvus 中,您可以尋找其值以指定前綴開頭的實體,如下所示:
res = client.query(
collection_name="my_collection",
filter='user like "ki%"',
output_fields=["id", "user"]
)
您可以在此頁面找到 Elasticsearch 的範例。有關 Milvus 中like 運算符號的詳細資訊,請參閱使用 LIKE 進行模式匹配。
範圍查詢
在 Elasticsearch 中,您可以尋找包含所提供範圍內詞彙的文件,如下所示:
resp = client.search(
query={
"bool": {
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
},
)
在 Milvus 中,您可以尋找特定欄位中的值在提供範圍內的實體,如下所示:
res = client.query(
collection_name="my_collection",
filter='10 <= age <= 20',
output_fields=["id", "user", "age"]
)
您可以在此頁面找到 Elasticsearch 的範例。有關 Milvus 中比較運算元的詳細資訊,請參閱比較運算元。
術語查詢
在 Elasticsearch 中,您可以尋找在所提供欄位中包含精確詞彙的文件,如下所示:
resp = client.search(
query={
"bool": {
"filter": {
"term": {
"status": {
"value": "retired"
}
}
}
}
},
)
在 Milvus 中,您可以如下查找指定欄位中的值正好是指定術語的實體:
# use ==
res = client.query(
collection_name="my_collection",
filter='status=="retired"',
output_fields=["id", "user", "status"]
)
# use TEXT_MATCH
res = client.query(
collection_name="my_collection",
filter='TEXT_MATCH(status, "retired")',
output_fields=["id", "user", "status"]
)
您可以在此頁面找到 Elasticsearch 的範例。有關 Milvus 中比較運算元的詳細資訊,請參閱比較運算元。
術語查詢
在 Elasticsearch 中,您可以尋找在所提供欄位中包含一個或多個精確詞彙的文件,如下所示:
resp = client.search(
query={
"bool": {
"filter": {
"terms": {
"degree": [
"graduate",
"post-graduate"
]
}
}
}
}
)
Milvus 並沒有完全等同的這個。但是,您可以尋找在指定欄位中值為指定詞彙之一的實體,如下所示:
# use in
res = client.query(
collection_name="my_collection",
filter='degree in ["graduate", "post-graduate"]',
output_fields=["id", "user", "degree"]
)
# use TEXT_MATCH
res = client.query(
collection_name="my_collection",
filter='TEXT_MATCH(degree, "graduate post-graduate")',
output_fields=["id", "user", "degree"]
)
您可以在此頁面找到 Elasticsearch 的範例。有關 Milvus 中範圍運算符的詳細資訊,請參閱範圍運算符。
通配符查詢
在 Elasticsearch 中,您可以尋找包含符合通配符模式的詞彙的文件,如下所示:
resp = client.search(
query={
"bool": {
"filter": {
"wildcard": {
"user": {
"value": "ki*y"
}
}
}
}
},
)
Milvus 在過濾條件中不支援通配符。但是,您可以使用like 運算符達到類似效果,如下所示:
res = client.query(
collection_name="my_collection",
filter='user like "ki%" AND user like "%y"',
output_fields=["id", "user"]
)
您可以在此頁面找到 Elasticsearch 的範例。有關 Milvus 中範圍運算符的詳細資訊,請參閱範圍運算符。
布林查詢
在 Elasticsearch 中,布林查詢是匹配其他查詢的布林組合的文件的查詢。
以下範例改編自本頁 Elasticsearch 文件中的範例。該查詢將傳回名稱中含有kimchy 的使用者,並附有production 標籤。
resp = client.search(
query={
"bool": {
"filter": {
"term": {
"user": "kimchy"
}
},
"filter": {
"term": {
"tags": "production"
}
}
}
},
)
在 Milvus 中,您可以做以下類似的事情:
filter =
res = client.query(
collection_name="my_collection",
filter='user like "%kimchy%" AND ARRAY_CONTAINS(tags, "production")',
output_fields=["id", "user", "age", "tags"]
)
上述範例假設您在目標集合中有一個VarChar類型的user 欄位和一個Array類型的tags 欄位。查詢將傳回名稱中包含kimchy 的使用者,並帶有production 標籤。
向量查詢
在 Elasticsearch 中,向量查詢是專門針對向量欄位來有效執行語意搜尋的查詢。
Knn 查詢
Elasticsearch 支援近似的 kNN 查詢和精確、粗暴的 kNN 查詢。您可以用這兩種方式找出與查詢向量最近的k 個向量,並以相似度指標衡量,如下所示:
resp = client.search(
index="my-image-index",
size=3,
query={
"knn": {
"field": "image-vector",
"query_vector": [
-5,
9,
-12
],
"k": 10
}
},
)
Milvus 作為專門的向量資料庫,使用索引類型來最佳化向量搜尋。通常,它優先對高維向量資料進行近似最近鄰 (ANN) 搜尋。雖然使用 FLAT 索引類型的暴力 kNN 搜尋能提供精確的結果,但卻既耗時又耗資源。相比之下,使用 AUTOINDEX 或其他索引類型的 ANN 搜尋能平衡速度與精確度,提供比 kNN 更快、更節省資源的效能。
在 Mlivus 中,與上述向量查詢的類似等式是這樣的:
res = client.search(
collection_name="my_collection",
anns_field="image-vector"
data=[[-5, 9, -12]],
limit=10
)
您可以在此頁面找到 Elasticsearch 的範例。有關 Milvus 中 ANN 搜尋的詳細資訊,請閱讀Basic ANN Search。
互惠排名融合
Elasticsearch 提供 Reciprocal Rank Fusion (RRF),可將具有不同相關性指標的多個結果集合併為單一排序結果集。
以下範例展示如何結合傳統的詞彙搜尋與 k-nearest neighbors (kNN) 向量搜尋,以改善搜尋的相關性:
client.search(
index="my_index",
size=10,
query={
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"term": {
"text": "shoes"
}
}
}
},
{
"knn": {
"field": "vector",
"query_vector": [1.25, 2, 3.5], # Example vector; replace with your actual query vector
"k": 50,
"num_candidates": 100
}
}
],
"rank_window_size": 50,
"rank_constant": 20
}
}
}
)
在這個範例中,RRF 結合了兩個檢索器的結果:
對
text欄位中包含"shoes"這個詞彙的文件進行標準的基於詞彙的檢索。使用提供的查詢向量對
vector欄位進行 kNN 搜尋。
每個擷取器會貢獻多達 50 個最頂尖的匹配結果,這些結果會由 RRF 重新排序,最後會傳回最頂尖的 10 個結果。
在 Milvus 中,您可以透過結合跨多個向量欄位的搜尋、套用重新排序策略,並從結合清單中擷取 Top-K 結果,來達到類似混合搜尋的目的。Milvus 支援 RRF 和加權 reranker 策略。如需詳細資訊,請參閱Reranking。
以下是上述 Elasticsearch 範例在 Milvus 中的非嚴格等化。
search_params_dense = {
"data": [[1.25, 2, 3.5]],
"anns_field": "vector",
"param": {
"metric_type": "IP",
"params": {"nprobe": 10},
},
"limit": 100
}
req_dense = ANNSearchRequest(**search_params_dense)
search_params_sparse = {
"data": ["shoes"],
"anns_field": "text_sparse",
"param": {
"metric_type": "BM25",
}
}
req_sparse = ANNSearchRequest(**search_params_sparse)
res = client.hybrid_search(
collection_name="my_collection",
reqs=[req_dense, req_sparse],
reranker=RRFRanker(),
limit=10
)
此範例展示了 Milvus 中的混合搜尋,它結合了:
密集向量搜尋:使用
nprobe設定為 10 的內積 (IP) 公制,在vector欄位上進行近似最近鄰 (ANN) 搜尋。稀疏向量搜尋:在
text_sparse欄位上使用 BM25 相似度指標。
這些搜尋的結果會分別執行、合併,並使用 Reciprocal Rank Fusion (RRF) 排序器重新排序。混合搜尋會返回重新排序清單中的前 10 個實體。
不同於 Elasticsearch 的 RRF 排序會合併標準文字式查詢和 kNN 搜尋的結果,Milvus 會合併稀疏和密集向量搜尋的結果,提供獨特的混合搜尋功能,針對多模式資料進行最佳化。
重溫
在這篇文章中,我們涵蓋了典型 Elasticsearch 查詢與 Milvus 等效查詢的轉換,包括術語級查詢、布林查詢、全文查詢和向量查詢。如果您對於轉換其他 Elasticsearch 查詢有進一步的問題,請隨時聯絡我們。