Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-23411

Inconsistent results when setting a nested field in $project

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: Aggregation Framework
    • None
    • Query
    • Fully Compatible
    • ALL

      If you use a non-inclusion dotted field during a $project stage, you can get different results depending on if the incoming document contains anything in that path:

      > db.foo.drop()
      true
      > db.foo.insert({a: [{b: 1}, {b: 2}]})
      WriteResult({ "nInserted" : 1 })
      > db.foo.aggregate([{$project: {"x.y": {$literal: 1}}}])
      // "x.y" didn't exist, so we created a nested field.
      { "_id" : ObjectId("56fae6c03ef38a5ce210b232"), "x" : { "y" : 1 } }
      > db.foo.aggregate([{$project: {"a.b": {$literal: 1}, c: "$a.b"}}])
      // "a.b" did exist, so we modified each value of "a.b" to be 1.
      { "_id" : ObjectId("56fae6c03ef38a5ce210b232"), "a" : [ { "b" : 1 }, { "b" : 1 } ], "c" : [ 1, 2 ] }
      

      What's even weirder is this behavior:

      > db.foo.find()
      { "_id" : ObjectId("56fae6c03ef38a5ce210b232"), "a" : [ { "b" : 1 }, { "b" : 2 } ] }
      > db.foo.aggregate([{$project: {"a.b": {$literal: 1}}}])
      // We created a nested field "a.b", even though there was previously a different structure in "a.b".
      { "_id" : ObjectId("56fae6c03ef38a5ce210b232"), "a" : { "b" : 1 } }
      

      Here the document did have something in "a.b", but nothing else was using it, so it was projected out, hence the different behavior from the example above, which specified {c: "$a.b"} so that the field "a.b" was needed, and hence remained in the incoming document.

      > db.foo.explain().aggregate([{$project: {"a.b": {$literal: 1}}}])
      {
      	"waitedMS" : NumberLong(0),
      	"stages" : [
      		{
      			"$cursor" : {
      				"query" : {
      					
      				},
      				"fields" : {
      					"_id" : 1
      				},
      ...
      
      > db.foo.explain().aggregate([{$project: {"a.b": {$literal: 1}, c: "$a.b"}}])
      {
      	"waitedMS" : NumberLong(0),
      	"stages" : [
      		{
      			"$cursor" : {
      				"query" : {
      					
      				},
      				"fields" : {
      					"a.b" : 1,
      					"_id" : 1
      				},
      ...
      

            Assignee:
            backlog-server-query Backlog - Query Team (Inactive)
            Reporter:
            charlie.swanson@mongodb.com Charlie Swanson
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: