Day 2 我們講解了「為什麼要有 query engine」
今天開始動手拆解它的骨幹:AST(抽象語法樹)與 Matcher tree
重點是三個最小元件:Eq
(等於)、Field
(取值)、And
(聚合)
把這三個拼起來,就能描述 8 成的日常條件
condition = {
"name": 'John',
"age": 30
}
背後想要的比對邏輯是:
a. 對資料欄位 name
取值,要等於 "John"
;
b. 對資料欄位 age
取值,要等於 30
;
c. 上述兩者都成立,才算匹配
我們將匹配的概念給展開成樹狀邏輯圖:
AND
├─ Field: "name"
│ └─ Eq: "John"
└─ Field: "age"
└─ Eq: 30
這個結構有幾個角色:
這就是 matcher tree 的雛形。
這個拆分讓我們能針對不同型別(如 String/Number)或不同來源(Hash/自訂物件)各自最佳化,同時保持語意單純
require 'mongory'
Mongory.enable_symbol_snippets!
Mongory.register(Array)
records = [
{ 'name' => 'John', 'age' => 30 },
{ 'name' => 'Mary', 'age' => 18 },
{ 'name' => 'John', 'age' => 25 }
]
q = records.mongory.where(:name => 'John', :age => 30)
q.each { |r| p r }
q.explain
輸出:
And: {"name"=>"John", "age"=>30}
├─ Field: "name" to match: "John"
│ └─ Eq: "John"
└─ Field: "age" to match: 30
└─ Eq: 30
今天我們 run 過了 AST 的最小積木:Eq
、Field
、And
明天(Day 4)會把進階運算子接上來:$gt/$gte/$in/$nin/$elemMatch
與針對陣列欄位的特殊處理,讓樹真正「長」起來
— 如果你已經有一段條件,歡迎把 q.explain
的輸出貼在 Issue,我可以在後續文章當範例解析