|
For the sub-object case:
db.c.insert({a: {b: 1}})
|
db.c.find({"a.b": 1}, {'a.$': 1}).toArray();
|
Which in 4.2 returned
[ { "_id" : ObjectId("5dc32e5dc382818df1a29263"), "a" : { } } ]
|
We'd take this path in projectionExec.
...
|
} else if (elt.type() == Object) {
|
BSONObjBuilder subBob;
|
BSONObjIterator it(elt.embeddedObject());
|
while (it.more()) {
|
subfm.append(&subBob, it.next(), details, arrayOpType).transitional_ignore();
|
}
|
bob->append(elt.fieldName(), subBob.obj());
|
} else {
|
...
|
When the element being appended was the 'b' field of 'a' subBob would be empty, so we'd end up appending an empty field. This feels like a bug. Whether it should have appended nothing or just left the field as-is is a separate question, but I think both are reasonable, and would like to leave the current 4.3 behavior (leaving the field as is).
For the case where 'a' is not an array, 4.2 is not even consistent between cases where a top-level field is being projected and a sub-field is being projected. Consider:
> db.c.insert({a: "astring"})
|
> db.c.find({"a": "astring"}, {'a.$': 1})
|
{ "_id" : ObjectId("5dc33418a2e1d48385a60bec") } // 'a' is missing entirely
|
> db.c.insert({a: {b: "astring"}})
|
> db.c.find({"a.b": "astring"}, {'a.b.$': 1})
|
{ "_id" : ObjectId("5dc3343ca2e1d48385a60bed"), "a" : { } } // We include an empty 'a' sub-object.
|
This whole feels like a bug to me. In 4.3 the behavior is more consistent.
> db.c.insert({a: "astring"})
|
WriteResult({ "nInserted" : 1 })
|
> db.c.find({"a": "astring"}, {'a.$': 1})
|
{ "_id" : ObjectId("5dc3372ecf7239995f220ee3"), "a" : "astring" } // 'a' is included entirely.
|
> db.c.insert({a: {b: "astring"}})
|
WriteResult({ "nInserted" : 1 })
|
> db.c.find({"a.b": "astring"}, {'a.b.$': 1})
|
{ "_id" : ObjectId("5dc336e6cf7239995f220ee1"), "a" : { "b" : "astring" } } // a.b' is included entirely.
|
I'd also just like to leave the behavior as-is here.
david.storch If you agree with this, then I will close as "Won't Fix" and update the design doc.
|