5

i have a mongo collection that looks like this:

{
    name: string
    _id: (auto set)
    items: array[
        name: string
        url: string
        items: array[
            {
                name: string,
                url: string,
                items: []
            }
        ]
    ]
}

I'm using findByIdAndUpdate (with mongoose) to add an item into the items array:

Menu.findByIdAndUpdate(
    req.body.parentid, 
    {
        $push: {
            items: {
                name: req.body.item.name, 
                url: req.body.item.url,
                items: []
            }
        }
    },
    {
        safe: true, 
        upsert: true, 
        new: true
    },
    function(err, model) {
        if (err !== null) {
            console.log(err);
        }
    }
);

This works fine, but it does not add an _id to each object inserted into the items array. And i really need an id for each one.

I'm guessing it comes from the method used, findByIdAndUpdate as it looks more like an update rather than an insert. If my thinking is correct.

Using mongodb 3.2.10 and mongoose 4.7.6.

Any help would be really appreciated. Thanks.

EDIT: the _id: (auto set) is not real, it's being automatically added via mongo. But just at the top level objects.

kevin
  • 618
  • 8
  • 24

3 Answers3

5

Found the solution in this thread: mongoDB : Creating An ObjectId For Each New Child Added To The Array Field

basically, added

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

and then forcing the creation:

$push: {
    items: {
        _id: new ObjectID(),
        name: req.body.item.name, 
        url: req.body.item.url,
        items: []
    }
}
Community
  • 1
  • 1
kevin
  • 618
  • 8
  • 24
0

You dont need to sepcify _id: (auto set) in mongoose schema it will automatically add unique _id with each document.

Asif Saeed
  • 1,985
  • 14
  • 24
  • What i thought, but, when i check via the mongo shell, i do not see any `_id` being added. Just for the top level objects where i wrote `_id: (auto set)`. – kevin Jan 16 '17 at 16:59
  • One other way of doing it _id: {type:ObjectIdSchema, default: function () { return new ObjectId()} } – Asif Saeed Jan 16 '17 at 17:07
  • Check in some other GUI like RoboMongo. There should be a unique id in the document it can be Auto Generated ObjectId with key '_id' – Asif Saeed Jan 16 '17 at 17:10
  • Yes i've checked with robomongo and there is really none. Check this screenshot: https://s27.postimg.org/iw7zftr6b/Screen_Shot_2017_01_16_at_15_12_19.png I'm gonna try your second comment. – kevin Jan 16 '17 at 17:14
  • ObjectId('587cd...') is the unique id generated with your document – Asif Saeed Jan 16 '17 at 17:18
  • Agreed. That one works fine. But my objects in the array item need one as well. – kevin Jan 16 '17 at 17:19
  • Ok i got your point you need unique ObjectIds in each Object in Items Array try this schema items: [{ name: string url: string items: [ { name: string, url: string, items: [] } ] } ] – Asif Saeed Jan 16 '17 at 17:24
  • Found the solution thanks to your help and this thread: http://stackoverflow.com/questions/35050750/mongodb-creating-an-objectid-for-each-new-child-added-to-the-array-field Thanks for the help! – kevin Jan 16 '17 at 17:27
  • As a follow up of @kevin's comment, if you are using mongoose, do NOT put _id explicitly in the doc type array elements and specify a default value, because this will assign the same _id to all the doc elements in the array. Just specify the fields other than _id. – fishstick Feb 08 '21 at 02:12
0

if you don't define _id in Schema, mongoose automatically add a _id to array item. for example:

const countrySchema = new Schema({
  name: {
    type: String
  },
  cities: [
    {
      // don't define _id here.
      name: String
    }
  ],
});

now when you insert a row, the result is something like this:

{name : 'Iran', cities : [{_id : 6202902b45f0d858ac141537,name : 'Tabriz'}]}

adel parsa
  • 236
  • 2
  • 5