Skip to content

Document.array.pull() does not seem to work for populated arrays when pulling an _id string #1635

Closed
@JedWatson

Description

@JedWatson

I have the following function designed to update the ObjectIds stored in a given document doc, at path, to match those provided in a form submission data by using atomic push and pull functionality.

(ObjectIds are stored in an array like this: schema.add({ myPath: [{type: ObjectId, ref: 'OtherSchema'}] });

function(doc, data, path) {

    var storedValue = doc.populated(path),
        arr = doc.get(path),
        _old = storedValue.map(function(i) { return String(i) }),
        _new = _.compact(data[path].split(','));

    console.log('Stored Value:');
    console.log(storedValue)

    console.log('Data at Path:');
    console.log(arr);

    console.log('Remove:');
    console.log(_.difference(_old, _new));

    // remove ids
    _.difference(_old, _new).forEach(function(val) {
        console.log('pulling ' + val);
        arr.pull(val);
    });

    console.log('Add:');
    console.log(_.difference(_new, _old));

    // add new ids
    _.difference(_new, _old).forEach(function(val) {
        console.log('pushing ' + val);
        arr.push(val);
    });

    console.log('Updated Value:');
    console.log(arr);

}

If the doc has already had path populated, two unexpected behaviours occur:

  1. ObjectIds aren't removed
  2. ObjectIds that are added exist in a half-populated state

Console.log output demonstrating both in the above function:

Stored:
[ 51f9fe338507730000000004 ]
Item Data:
[ { name: 'Jimmy',
  _id: 51f9fe338507730000000004 } ]
Remove:
[ '51f9fe338507730000000004' ]
pulling 51f9fe338507730000000004
Add:
[ '51f9fe338507730000000007' ]
pushing 51f9fe338507730000000007
Updated:
[ { name: 'Jimmy',
  _id: 51f9fe338507730000000004 }, { _id: 51f9fe338507730000000007 } ]

re: 1, this seems like a bug. The documentation here implies that you should be able to remove ids from an array, although it doesn't mention what happens if the array has been populated.

re: 2, as you can see the newly added object looks populated (is an object) but hasn't been loaded from the database yet (so has no name property). What's the best way to handle this? Repopulate the path after saving the document?

It might be best in my particular case to specifically detect that the path being updated has been populated, unpopulate it, make the atomic changes to the array, then repopulate the path after the document has been saved. There doesn't seem to be any api to unpopulate a path, and I don't want to blindly do this:

document.set(path, document.populated(path));

... because I think that would cause the document to think that the entire value of path has been modified.

Any hints on how to best make all this work would be great, Cheers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementThis issue is a user-facing general improvement that doesn't fix a bug or add a new feature

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions