10

I'm trying to specify the schema of my db in mongoose. At the moment I do this:

var Schema = mongoose.Schema;  
var today = new Date(2011, 11, 12, 0, 0, 0, 0);


var personSchema = new Schema({  
   _id : Number,
   name: { type: String, required: true },  
   tel: { type: String, required: true },  
   email: { type: String, required: true },
   newsitems: [{ type: Schema.Types.ObjectId, ref:'NewsItem'}]
});

var taskSchema = new Schema({ 
    _id: Number,
    description: { type: String, required: true },  
    startDate: { type: Date, required: true },
    newsitems: [{ type: Schema.Types.ObjectId, ref:'NewsItem'}]
});

var newsSchema = new Schema({
    _id: Number,
    creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    task : { type: Schema.Types.ObjectId, ref: 'Task' },
    date: { type: Date, required:true },
    loc: {type: String, required: true }  
});

var NewsItem  = mongoose.model('NewsItem', newsSchema);
var Person = mongoose.model('Person', personSchema);
var Task = mongoose.model('Task', taskSchema);



var tony = new Person({_id:0, name: "Tony Stark", tel:"234234234", email:"tony@starkindustries.com" });
var firstTask = new Task({_id:0, description:"Get an interview with the president", startDate:today});
var newsItem1 = new NewsItem({_id:0, creator: tony.id, task: firstTask.id, date: today, loc: "NY"});

newsItem1.save(function (err) {
  if (err) console.log(err);

    firstTask.save(function (err) {
        if (err) console.log(err);
    });

    tony.save(function (err) {
         if (err) console.log(err);
    }); 
});



NewsItem
.findOne({ loc: "NY" })
.populate('creator')
.populate('task')
.exec(function (err, newsitem) {
  if (err) console.log(err)
    console.log('The creator is %s', newsitem.creator.name);
})

I create the schemas and try to save some data.

The error:

{ message: 'Cast to ObjectId failed for value "0" at path "creator"',
  name: 'CastError',
  type: 'ObjectId',
  value: '0',
  path: 'creator' }

I wrote this code based on : http://mongoosejs.com/docs/populate.html#gsc.tab=0

The db I try to create looks like this: Specify schema in mongoose .

How can I fix this?

Community
  • 1
  • 1
Olivier_s_j
  • 5,490
  • 24
  • 80
  • 126

2 Answers2

14

The example from the mongoose docs you referenced uses Number for the personSchema._id field, and ObjectId for the others.

I presume they do this in the example only to demonstrate that it's possible to use either. If you do not specify _id in the schema, ObjectId will be the default.

Here, all your records have an _id field which is an ObjectId, yet you're treating them like numbers. Furthermore, fields like personID and taskID do not exist, unless you've left out the part where you define them.

If you did want to use numbers for all your _id fields, you'd have to define that in the schemas.

var newsSchema = new Schema({
  _id: Number,
  _creator: {type: ObjectId, ref: "Person"},
  // ...
})

var personSchema = new Schema({
  _id: Number,
  // ...
})

Then to create a news item with a particular ID, and assign it to a creator:

var tony = new Person({_id: 0});
var newsItem = new NewsItem({_id: 0, creator: tony.id});

However the thing to note here is that when you use something other than ObjectId as the _id field, you're taking on the responsibility of managing these values yourself. ObjectIds are autogenerated and require no extra management.

Edit: I also noticed that you're storing refs on both sides of your associations. This is totally valid and you may want to do it sometimes, but note that you'd have to take care of storing the references yourself in the pre hook.

numbers1311407
  • 33,686
  • 9
  • 90
  • 92
  • thx for the help, though when querying and populating, I get an error. Do you happen to know what I did wrong ? (updated the question) – Olivier_s_j Apr 02 '13 at 19:07
  • Did you save them? It seems like it should work, unless it's loading a previous news item which was saved without a creator. – numbers1311407 Apr 02 '13 at 19:10
  • I added the save part to the question and the error which it triggers – Olivier_s_j Apr 02 '13 at 19:15
  • Like I said in the answer, the `creator` ref needs to be of type `Number`, not `ObjectId`. And yeah, your code above is incorrect. The `findOne` query would need to be inside the callback to be able to retrieve those new records. And also, if you're not dumping the db in between running this script, you're just loading the first one matching "NY" repeatedly anyway. – numbers1311407 Apr 02 '13 at 19:19
  • So I should save the task and person first and then the newsitem ? – Olivier_s_j Apr 02 '13 at 19:24
  • You're determining the id before you even save, it doesn't matter the order you save them, but *none of those saves* are happening before your find query as `save` is asynchronous. – numbers1311407 Apr 02 '13 at 19:27
  • Ok that makes sense. But you're saying that the creator ref needs to be of type Number, do you mean the id of the personSchema ( which is a number)? or the creator attribute in newsSchema which is a ObjectId in your solution too ? – Olivier_s_j Apr 02 '13 at 19:32
  • The creator attribute. A mongoose db ref needs to match the type of the _id it's referencing. – numbers1311407 Apr 02 '13 at 19:36
  • ok got it, if I check the value after it is saved I get the correct name. thx a lot ! :) – Olivier_s_j Apr 02 '13 at 19:37
5

I was receiving this error after creating a schema: CastError: Cast to ObjectId failed for value “[object Object]” at path “_id” Then modifying it and couldn't track it down. I deleted all the documents in the collection and I could add 1 object but not a second. I ended up deleting the collection in Mongo and that worked as Mongoose recreated the collection.

Enkode
  • 4,515
  • 4
  • 35
  • 50
  • I was receiving a similar error from passport, I just re-created to make sure I got exact: `Error: Unknown authentication strategy "[object Object]"` - this is due to using `jwt` the reference to the node package, and not `'jwt'` the string, e.g. passport constructor: `passport.authenticate('jwt', { session: false, });` – AveryFreeman Mar 21 '22 at 17:36