Milvus 向量數據庫如何實現屬性過濾

編者按:本文詳細介紹 Milvus 2.0 如何對查詢節點的數據進行管理,以及如何提供查詢能力。
  • 查詢表達式的文法規則

    • Milvus 支持的查詢表達式

    • 底層操作服務及具體表達式

  • 查詢語法的生成

    • 開源工具 ANTLR 介紹

    • PlanAST generation

  • 語法樹的解釋和執行

    • PlanAST & Expr definition

    • PlanAST execution


查詢表達式的文法規則

Milvus 支持的查詢表達式

如下圖所示,Milvus 運用 EBNF 語法,此處用等式和語法圖體現了 Milvus 所支持的查詢表達式的整體規則。

表達式 LogicalExpr 有四種組合來進行表示,比如通過二元的邏輯運算符,在邏輯表達式前加一元的邏輯運算符,或者用一些比較簡單的 Single Expr 等。

由於 EBNF 本身就是一個遞歸的結構,LogicalExpr 既可以是這四條組合起來的整體,也可以是其中單獨的某個節點,並且可以繼續嵌套下去。也就是說,Milvus 支持的表達式規則是可以無限的遞歸嵌套的。如果有很多屬性需要過濾,就可以通過不同的組合和嵌套,進而表示出需要的過濾條件。

底層操作服務及具體表達式

上圖是前文提到的幾種表達式。首先可以在表達式前面加單元的邏輯運算符,目前 Milvus 支持的是添加 “not”,表示在表達式做出計算以後取它的非。其次二元邏輯運算符就是與和或的兩種不同表現方法。然後 Single Expr 目前實現的是 Term 和 Compare 。

另外如基本的加減乘除等其他運算也是支持的。下圖是操作服務的優先級,由 1 - 9 遞減。


查詢語法的生成

開源工具 ANTLR 介紹

ANTLR 可以理解爲解析器或者生成器,它能夠對結構化文本或者二進制文件做讀處理,包括執行和翻譯的過程。具體來說,ANTLR 可以根據定義的文法規則進行解析,也可以生成解析器來構建解析數;同時它內部也提供了 WALKER 的一些 API,可以幫助遍歷解析數。例如圖中的表達式 “SP =100;" ,ANTLR 自帶的語言識別器 LEXER 會生成四個 token,再各自進行解析生成 Parse-Tree。

其中比較重要的功能是給生成的 Parse-Tree 提供了 WALKER 的機制,通過 WALKER 對這解析數進行遍歷。比如每個節點是否符合文法規則、單詞有無涉及敏感詞彙,都可以得到合法性檢查。從右邊列出的 Parse-Tree 遍歷的 API 可以看出,ANTLR 從 根節點一直到最末端的子節點,是按照一種深度遍歷的順序來進行遍歷的,由此也不需要人爲區分多叉樹的前序、中序、後序,直接看API即可。

PlanAST generation

Milvus 的運作方法和 ANTLR 較爲相似,但後者比較原始化,需要根據需求重新定義相對複雜的文法規則。Milvus 使用的 expression 這種同樣常見的語法規則,並且依靠 GitHub上 ant-expr 這一開源工具來實現生成語法的查詢與解析。

首先用戶會傳過來一個表達式 expression ,然後通過 ant-parser(這個包含在 ant-expr 裏)的 Parse 方法 ,可以生成一個比較原始的 Unsolved Plantree 。就是前面提及的通過四大分析和簡單的 Parse 後生成一個簡單的二叉樹,這個二叉樹都是 ant-expr 內部的一些結構來表示。接下來對這個 Plantree 做一些 optimizer ,這個 optimizer 是 Milvus 自己實現的。類似於前面講的 WALKER 的機制,遍歷並且給每種節點實現一些優化器。由於 ant-expr 本身生成的優化樹功能已經較好,對後續做執行、解析都比較友好,此處的 optimizer 工作也較爲簡單。

最後一個這個虛線節點的 analyzer 過程是將已經優化好的 Plantree 進行遞歸遍歷分析。在二叉樹的遍歷過程中,每個節點對應到定義的 protobuf 的語法樹的結構,進而生成一個 protobuf 結構的一個 plan AST (abstract syntax tree)。

語法樹的解釋和執行

PlanAST & Expr definition

Milvus 裏定義了一種 proto 結構來表示前文提及的 plan AST 抽象語法樹。如圖中右上角定義的一個 protobuf 結構的 message,查詢方式就是通過 expression 得到,且 Expr 有六種選擇,其中 BinaryExpr 和 UnaryExpr 存在進一步遞歸的 LogicalExpr。

上圖爲表達式的一個 UML 的圖,是 C++ 中根據 proto 結構去實現類的繼承關係結構圖,包含各個 Expr 的基類與派生類。每個類下面都實現了一個 accept 的方法,接受的是 visitor 的參數。這就是典型的訪問者設計模式(Visitor design pattern),以此對前面生成的查詢語法樹進行遍歷的執行。這一模式的優勢在於用戶不需要對 Expr 原始進行操作,可以直接通過訪問的方法對其中一些具體的類與元素進行修改。

PlanAST execution

上圖總結了查詢語法樹執行的工作流程。首先從 C++ 接收到一個 proto 類型的 PlanNode,經過 C++ 內部的 ProtoParse 得到 segcore 類型的 PlanNode。在此基礎上,通過 accept 的方法接受一系列的訪問者類,再對 PlanNode 內部的結構進行修改、執行。最後對每個具體的ExecPlanNode進行遞歸遍歷,得到過濾的結果 Filtered_result,以下圖的Bitmap作爲具體形式。


完整版視頻講解請戳:https://www.bilibili.com/video/BV1h44y1v7S8/

如果你在使用的過程中,對 Milvus 有任何改進或建議,歡迎在 GitHub 或者各種官方渠道和我們保持聯繫~


Zilliz 

Zilliz  Milvus Milvus  LF AI & Data 用。


閱讀原文,解鎖更多應用場景

本文分享自微信公衆號 - ZILLIZ(Zilliztech)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章