Reputation: 24063
I am using mongoose and I have two models: Item and Hashtag.
Hashtag model should contain only name and Item model should contain a list of hashtags (represented by ids).
This is what I've done:
var ItemSchema = new Schema({
hashtags: [ { type: Schema.ObjectId, 'default': null, ref: 'Hashtag' } ],
});
var HashtagSchema = new Schema({
name: { type: String, 'default': '', trim: true },
items: [{ type: Schema.ObjectId, ref: 'Page' }]
});
This is how I try to create an Item:
var item = new Item({
hashtags: ['a', 'b', 'c']
});
item.save(function (err, item) {
if (err) return res.json({ error: err });
res.json(item);
});
Unfortunately I get this error:
CastError: Cast to ObjectId failed for value "a,b,c" at path "hashtags"
How can I solve this?
Upvotes: 0
Views: 3029
Reputation: 14062
Since you are using references instead of subdocuments, you need to create the hashtag objects first:
var tagnames = ['a','b','c'];
var hashtags = {}; //for referencing quickly by name later
for (var h in tagnames){
var tag = new Hashtag({
name: tagnames[h]
});
tag.save(function (err, item) {
if (err) console.log('error:',err);
hashtags[item.name] = item;
});
}
Once you have the hashtags created, you can reference them::
var item = new Item({
hashtags: [hashtags.a._id,hashtags.b._id,hashtags.c._id]
});
item.save(function (err, item) {
if (err) return res.json({ error: err });
res.json(item);
});
Then you can use populate to automatically turn the object ids into documents:
Item.find({})
.populate('hashtags')
.exec(function (err, items) {
if (err) return handleError(err);
//items are populated with hashtags
});
If you are just doing simple tagging, then subdocuments may be a better fit. They allow you to declare and save child documents all in one step. The trade-off is that subdocuments belong exclusively to their parent documents. They are not references so any aggregations on them must be done manually.
Upvotes: 2