-
Type: Task
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
Query Execution
-
QE 2023-05-15
-
10
Consider the projection {_id: 0, "a.b.c": 1}. Currently, the projection stage builder will produce the following plan:
[2] project [s6 = traverseP(s4, lambda(l1.0) { if isObject(l1.0) then makeBsonObj(MakeObjSpec(keep, [], ["a"]), l1.0, traverseP(getField(l1.0, "a"), lambda(l2.0) { if isObject(l2.0) then makeBsonObj(MakeObjSpec(keep, [], ["b"]), l2.0, traverseP(getField(l2.0, "b"), lambda(l3.0) { if isObject(l3.0) then makeBsonObj(MakeObjSpec(keep, ["c"], []), l3.0) else Nothing }, Nothing)) else Nothing }, Nothing)) else Nothing }, Nothing)] [1] scan s4 s5 none none none none [] @"9b7f08cc-f7c3-4d13-957a-a824db1bb046" true false
This plan makes use of the `makeBsonObj` vm instruction. Compare this to the plan generated by the optimizer, which uses keep/dropFields to implement the projection:
plan : [2] project [s2 = let [ l101.0 = if isObject(s1) then keepFields(s1, "a") else s1 ] in let [ l102.0 = traverseP(getField(l101.0, "a"), lambda(l103.0) { let [ l104.0 = let [ l105.0 = if isObject(l103.0) then move(l103.0) else Nothing ] in if isObject(l105.0) then keepFields(move(l105.0), "b") else move(l105.0) ] in let [ l106.0 = traverseP(getField(l104.0, "b"), lambda(l107.0) { let [ l108.0 = if isObject(l107.0) then move(l107.0) else Nothing ] in if isObject(l108.0) then keepFields(move(l108.0), "c") else move(l108.0) }, Nothing) ] in if (exists(l106.0) || isObject(l104.0)) then setField(move(l104.0), "b", move(l106.0)) else move(l104.0) }, Nothing) ] in if (exists(l102.0) || isObject(l101.0)) then setField(move(l101.0), "a", move(l102.0)) else move(l101.0)
This ticket tracks the work to replace MakeObjSpec with keep/dropFields and to remove MakeObjSpec