-
Type:
Task
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
Query Execution
-
QE 2023-05-15
-
10
-
None
-
None
-
None
-
None
-
None
-
None
-
None
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