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

Automatically create necessary subdoc structure from "dot" notation on updates when fields are null

    • Type: Icon: Improvement Improvement
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 2.0.3, 2.1.0
    • Component/s: Write Ops
    • Labels:
      None
    • Query Optimization

      From discussion on user group:
      http://groups.google.com/group/mongodb-user/browse_thread/thread/dfdbf0cc4a6a5891

      When performing updates involving subdocuments, it would greatly simplify the edge cases which need to be handled client-side if the server would automatically create the necessary subdocument(s) indicated by the "dot" notation in the update when fields in chain are null (instead of the LEFT_SUBFIELD error that is currently returned). This would align the behavior more towards how it currently behaves when fields in the chain do not exist.

      However, I would expect the LEFT_SUBFIELD error if a field is currently a non-null primitive since you wouldn't want to automatically overwrite that primitive data (which is current behavior).

      One common use case where this would have a very positive impact is in data migrations. In migrations you often may need to replace a null field with a subdoc as schemas evolve but may not know (or want to worry about) whether that field is currently null (preventing sometimes expensive/complex document introspection prior to updating).

      Current behavior when fields don't exist:

      > db.testing.insert({"id":1})
      > db.testing.update({"id":1}, {$set: {"data.id" : 1}})
      > db.testing.find({"id":1})
      { "_id" : ..., "data" : { "id" : 1 }, "id" : 1 }
      > db.testing.update({"id":1}, {$set: {"data.sub.sub.sub" : 1}})
      > db.testing.find({"id":1})
      > { "_id" : .., "data" : { "id" : 1, "sub" : { "sub" : { "sub" : 1 } } }, "id" : 1 }
      

      Current behavior when field is null:

      > db.testing.insert({"id":2, "data":null})
      > db.testing.update({"id":2}, {$set: {"data.id" : 1}})
      LEFT_SUBFIELD only supports Object: data not: 10 
      

      Desired behavior when field is null (same as when fields don't exist):

      > db.testing.insert({"id":2, "data":null})
      > db.testing.update({"id":2}, {$set: {"data.id" : 1}})
      > db.testing.find({"id":1})
      { "_id" : ..., "data" : { "id" : 1 }, "id" : 2 }
      

      Maintain current behavior when field is non-null primitive:

      > db.testing.insert({"id":3, "data":"non-null primitive"})
      > db.testing.update({"id":3}, {$set: {"data.id" : 1}})
      LEFT_SUBFIELD only supports Object: data not: 2
      

            Assignee:
            backlog-query-optimization [DO NOT USE] Backlog - Query Optimization
            Reporter:
            calebjones Caleb Jones
            Votes:
            18 Vote for this issue
            Watchers:
            18 Start watching this issue

              Created:
              Updated: