0

I am writing a Node/Express/Mongoose (latest versions) application which has "Projects" with a list of "collaborators" which are IDS of "Users". Until now, I've been storing the list of foreign keys as hex strings. This is now making it difficult to perform some slightly more complex aggregation, so I have decided to store them as ObjectId type instead, which makes the joins simpler.

In the function which creates the array, the push(userId) version works fine, adding collaborators to the array. However pushing an ObjectId into the array, or assigning an array containing an ObjectId fails with

"The dollar ($) prefixed field '$conditionalHandlers' in 'collaborators..$conditionalHandlers' is not valid for storage."

function addCollaborator(projectId, userId, fn){
    projectModel.findById(projectId, (err, project)=>{
        if(err) return fn(err);

        project.collaborators.push( new Schema.Types.ObjectId(userId)); // errors
        // project.collaborators = [ new Schema.Types.ObjectId(userId) ]; // errors
        // project.collaborators.push( userId); // works

        project.save((err)=>{
            logService.error('Error adding collaborator to project: '+err.toString());
        });
        fn(null);
    });
}

Project model:

const ProjectSchema = new mongoose.Schema({
        name: String,
        create_date: Date,
        administrators: Array,          // list of user._id
        collaborators: Array,           // list of user._id ObjectIds
    });

With the text IDs, I get projects looking like:

{ "_id" : ObjectId("594e2222a26ca3505c18c674"), 
"name" : "Pips 2nd Project", "create_date" : ISODate("2017-06-24T08:26:10.498Z"), 
"collaborators" : [ "5936a3576d6c5a3ef4ee0936" ], 
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 1 }

When it breaks, I log the error, and am left with an empty array:

{ "_id" : ObjectId("594e278b6a68a2815b043bd1"), 
"name" : "Pips third Project", "create_date" : ISODate("2017-06-24T08:49:15.091Z"), 
"collaborators" : [ ], 
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 0 }

What I want to achieve is:

{ "_id" : ObjectId("594e2222a26ca3505c18c674"), 
"name" : "Pips 2nd Project", "create_date" : ISODate("2017-06-24T08:26:10.498Z"), 
"collaborators" : [ Object("5936a3576d6c5a3ef4ee0936") ], 
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 1 }

I've seen a few other SO's or github issues, but none seem to explain the problem. This one has the same problem, but "solved" it by using strings - which is the opposite of my issue.

scipilot
  • 6,681
  • 1
  • 46
  • 65

1 Answers1

0

After reading some other posts (e.g.), I realised I was using the wrong method to create an ObjectId from a hex string.

new Schema.Types.ObjectId(userId) // not right!

Should be:

mongoose.Types.ObjectId(userId)

So this works as expected now:

project.collaborators.push( mongoose.Types.ObjectId(userId));

and produces:

{ "_id" : ObjectId("594e278b6a68a2815b043bd1"), 
"name" : "Pips third Project", "create_date" : ISODate("2017-06-24T08:49:15.091Z"), 
"collaborators" : [ ObjectId("5936a3576d6c5a3ef4ee0936") ],
"administrators" : [ "594dbba8186f1a2f5ad7539c" ], "__v" : 1 }
scipilot
  • 6,681
  • 1
  • 46
  • 65