Toli
Toli

Reputation: 5777

In Mongoose how do I create a MongooseArray/Collection in a model that has .create(), .id(), and .remove() functionality

My Schemas:

Account: mongoose.model('Account', new Schema({
    account_name: String,
    company: String,
    notes: String,
    contact_info: [this.ContactInfo]
})),
ContactInfo: mongoose.model('ContactInfo', new Schema({
    name: String,
    email: String,
    phone: String,
    notes: String 
}))

When I try to do any actions on contact_info though, it says that the methods don't exist.

var c = new ContactInfo...);
var a = new Account(...);

a.contact_info.create(c); //error, create doesn't exsit
a.contact_info.push(c); //works
a.contact_info.id(...).remove(); //id doesn't exist

Am I doing something wrong?

My full code is here (not too much of it): https://github.com/nycitt/node-survey-builder-api-server/blob/master/accounts.js

I'm receiving input from Backbone.js by the way

Upvotes: 1

Views: 1175

Answers (2)

Toli
Toli

Reputation: 5777

So apparently I did a few things wrong:

In Schemas, reference other Schemas NOT Models:

Good:

var ContactInfoSchema = new Schema({
    name: String
});

var AccountSchema = new Schema({
    account_name: String,
    contact_info: [ContactInfoSchema] 
});

var ContactInfo = mongoose.model('ContactInfo', ContactInfoSchema);

var Account = mongoose.model('Account', AccountSchema);

Bad: var ContactInfoSchema = new Schema({ name: String, email: String, phone: String, notes: String });

var AccountSchema = new Schema({
    account_name: String,
    contact_info: [ContactInfo] //subtle difference
});

var ContactInfo = mongoose.model('ContactInfo', ContactInfoSchema);

var Account = mongoose.model('Account', AccountSchema);

The other thing is doing the following doesn't save anything!!!

account.contact_info.create(params);
account.save();

You also have to do

var c = account.contact_info.create(params);
account.contact_info.push(c);
account.save();

For those interested here are the CRUD methods I created for Account and ContactInfo.

https://github.com/nycitt/node-survey-builder-api-server/blob/f94fcd4b05bf0af4f34a0e00f4ff79ebf64e24e1/accounts.js

Upvotes: 1

Jonathan Lonowski
Jonathan Lonowski

Reputation: 123513

Your issue may be within schemas.js. When defining an object by literal, this won't refer to the object being defined:

// ...
    contact_info: [this.ContactInfo]
// ...

It'll instead refer to the context surrounding the literal -- in the case of Node modules, the exports object -- which doesn't have a ContactInfo property. So, the result is:

// ...
    contact_info: [undefined]
// ...

You'll still have an Array, which is why push is available. But, Mongoose doesn't know to make it a MongooseDocumentArray, so it won't have the id, create, etc. methods.

You'll have to define your models outside the object to have a reference to them. Also note the change in order:

var ContactInfo = mongoose.model('ContactInfo', new Schema({
    // ...
});

var Account = mongoose.model('Account', new Schema({
    // ...
    contact_info: [ContactInfo]
});

module.exports = {
    Account: Account,
    ContactInfo: ContactInfo
};

Or, attach them to exports so this.ContactInfo is set (same order):

exports.ContactInfo = ...;
exports.Account = ...;

Upvotes: 1

Related Questions