Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoDB : Creating An ObjectId For Each New Child Added To The Array Field

Tags:

mongodb

mongodb 2.1.4(The Node Driver)

I'm currently trying to create a new ObjectID for each message I insert into an array(the array being a subdocument).

I figure this way - All CRUD operations can easily be performed on each message in the array.

For Example:

The "threads" collection(Note- An ObjectId for each message)

{
    "_id": ObjectId("1234132413424123"), //A thread id
    messages:[
        {
            _id :ObjectId("134124412341234"),// A message id
            "message":"MongoDB is my friend"

        },
        {
            _id :ObjectId("534124412342377"),
            "message":"MongoDB is my friend too"

        },
        ...
    ]
},
{
    "_id": ObjectId("22341324134224234"),
    messages:[
        {
            _id :ObjectId("8341244123411235"),
            "message":"Something clever"

        },
        {
            _id :ObjectId("134124412342376"),
            "message":"blah blah blah"

        },
        ...
    ]
}

What I'm currently doing right now:

var query = {};

query["_id"] = new ObjectID(threadID);

var update = {$push: {}};    //I write the update object externally just for aesthetics

update.$push["messages"] = newMessage; 

var threadsCollection = db.collection('threads');
threadsCollection.findOneAndUpdate(query,update, function (err, result) {
    if (err) {
        console.log(err);
    } 
    db.close();
});

Problem:

Unlike "insert" for collections, an update with $push does not create a new ObjectId for each message added to the array.

Question:

Is there a standard way of creating an ObjectID during a $push into the child array? Or should we just manually create an ObjectID and add it to the child beforehand?

like image 422
Nick Pineda Avatar asked Jan 28 '16 00:01

Nick Pineda


1 Answers

Not a mongodb expert but, if I understand you correctly, you wish the _id field of the subdocument to be inserted automatically.

I created threads db and then inserted the first message in the messages collection using the following command:

db.messages.insert({messages:[{_id:ObjectId(), message:"Message 1."}]}); 

Notice the _id:ObjectId() field. The result is as follow:

enter image description here

Now that I have an ObjectId(56...), I can update that particular record and insert more messages to it. And the command is as follow:

db.messages.update({"_id":ObjectId("56...")}, 
{$push:{messages:{_id:ObjectId(), message:"I am message 2."}}});

And the above would insert the new message in the collection. See below screenshots:

enter image description here

and finally after a few updates the collection looks as follow:

enter image description here

All the _id fields in the messages array are automatically generated.

It might not be a good idea to use _id fields for various reasons. Please Google for more details on whether to use _id as key for subdocuments or not.

I used MongoDB shell version 3.0.6 for the commands.

EDIT 28-01-2016 16:09

Since the above solution was based on MongoDB shell, I decided to do another test using Node.js driver for MongoDB. First of all, I declare ObjectID variable as follow

var ObjectID = require('mongodb').ObjectID;

I will use the ObjectID with document id of the thread to which the message should be inserted as follow in my update and findOneAndUpdate function calls

app.get('/insertNewMessage', function(req, res) {
    db.collection("messages").findOneAndUpdate({
        _id: new ObjectID('56aa3554e90911b64c36a424')
    }, {
        $push: {
            messages: {
                _id: new ObjectID(),
                message: "From NodeJS with <3 using findOneAndUpdate.Bye."
            }
        }
    }, function(err, result) {
        if (err)
            res.json(err);
        else
            res.json(result);
    });
});

Tested both and works just fine. See the screenshot below:

enter image description here

like image 86
Raf Avatar answered Nov 12 '22 17:11

Raf