|
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
|