Guilherme
Guilherme

Reputation: 1990

Mongoose self referenced schema not creating ObjectId for all sub documents

I have a Schema in mongoose that have a self referenced field, like this:

var mongoose = require('mongoose');

var CollectPointSchema = new mongoose.Schema({
  name: {type: String},
  collectPoints: [ this ]
});

when a CollectPoint object is inserted:

{
  "name": "Level 1"
}

it's ok, the result is like expected:

{
  "_id": "58b36c83b7134680367b2547",
  "name": "Level 1",
  "collectPoints": []
}

But when I insert self referenced sub documents,

{
  "name": "Level 1",
  "collectPoints": [{
    "name": "Level 1.1"
  }]
}

It gives me this:

{
  "_id": "58b36c83b7134680367b2547",
  "name": "Level 1",
  "collectPoints": [{
    "name": "Level 1.1"
  }]
}

Where is the _id of the child CollectPointSchema? I need this _id.

Upvotes: 1

Views: 268

Answers (1)

Bertrand Martel
Bertrand Martel

Reputation: 45493

You should build a new object when declaring your embedded CollectPoint items :

var data = new CollectPoint({
    name: "Level 1",
    collectPoints: [
        new CollectPoint({
            name: "Level 1.1",
            collectPoints: []
        })
    ]
});

This way the _id and collectPoints will be created by the instanciation of CollectPoint otherwise, you are just creating a plain JSONObject.

To avoid those kind of issues, build a validator for your array that will trigger an error if its items have wrong type :

var CollectPointSchema = new mongoose.Schema({
    name: { type: String },
    collectPoints: {
        type: [this],
        validate: {
            validator: function(v) {
                if (!Array.isArray(v)) return false
                for (var i = 0; i < v.length; i++) {
                    if (!(v[i] instanceof CollectPoint)) {
                        return false;
                    }
                }
                return true;
            },
            message: 'bad collect point format'
        }
    }
});

This way the following will trigger an error :

var data = new CollectPoint({
    name: "Level 1",
    collectPoints: [{
        name: "Level 1.1",
        collectPoints: []
    }]
});

Upvotes: 1

Related Questions