1

I want to define a method on my model that involves searching the documents of the same model, here is what I tried:

var mongoose = require('mongoose');
var Author = require('./author.js'); 

var bookSchema = mongoose.Schema({
    author : { type: mongoose.Schema.Types.ObjectId, ref: 'author' },
    genre: String,
});

bookSchema.methods.findSimilar = function(callback) {
    bookSchema.find({'genre': this.genre}).exec(function doThings(err, doc){ 
        /* ... */ 
    }); 
}; 
module.exports = mongoose.model('book', bookSchema, 'book');

However, I get TypeError: bookSchema.find is not a function.

I also tried bookSchema.methods.find(), same result. How can I fix this?

Thanks,

Edit: Inspired by this answer, I also tried this.model('Book').find(), but I get a similar error: TypeError: this.model is not a function

1

2 Answers 2

1

Change your method to: (I assume you have already exported model Book from your schema module.

bookSchema.methods.findSimilar = function(callback) {

    this.model('Book').find({'genre': this.genre}).exec(function doThings(err, doc){ 
        /* ... */ 

    }); 

    // Or if Book model is exported in the same module
    // this will work too:
    // Book.find({'genre': this.genre}).exec(function doThings(err, doc){ 
    //     /* ... */ 
    //    
    // }); 
};

The method will be available on the instance of your model:

var book = new Book({ author: author_id, genre: 'some_genre' });
// Or you could use a book document retrieved from database

book.findSimilarTypes(function(err, books) {
    console.log(books);
});

See documentation here.

EDIT (Complete Schema/Model Code)

The complete schema/model code will be as follows:

var mongoose = require('mongoose');
var Author = require('./author.js'); 

var BookSchema = mongoose.Schema({
    author : { type: Schema.Types.ObjectId, ref: 'Author' },
    genre: String,
});

BookSchema.methods.findSimilar = function(callback) {
    Book.find({genre: this.genre}).exec(function doThings(err, doc){ 
        /* ... */ 
    }); 
}; 

const Book = module.exports = mongoose.model('Book', BookSchema);

Usage example:

var book = new Book({ author: author_id, genre: 'some_genre' });
// Or you could use a book document retrieved from database

book.findSimilarTypes(function(err, books) {
    console.log(books);
});
12
  • Did you create a model for this schema? If you exported a model for this schema from the same module (named Book), you can use Book.find({'genre': this.genre}).exec(function doThings(err, doc) { // ... // }) Commented Jan 15, 2017 at 10:01
  • I thought this file was the model :) In other files, I include this like var Book = require('./models/thisfile'); and then do Book.find(..). I can define my methods on external files (like controllers) but I just wonder if I can make it part of the model. Edit: I forgot the last line where I do module.exports = .... But it's confusing. Should I define the function before I export the model, or after? Neither seems logical right now :D
    – jeff
    Commented Jan 15, 2017 at 10:02
  • I got confused with PascalCasing & CamelCasing in your code. Usually we use PascalCasing for schema & models and camelCasing for instances. See my edit above. I have included complete code for how your schema/model module should be. Hope this helps. Commented Jan 15, 2017 at 10:16
  • Thank you so much! This is still confusing me, the Book inside findSimilar is defined after the function definition. How does it work? And what does the const do? Again, thanks a lot.
    – jeff
    Commented Jan 15, 2017 at 10:28
  • 1
    Ah ok... You are doing Book.find() and that will return array of doc. So you must call doc[0].save(). You have another option of using Book.findOne() which returns single doc and in that case you can call doc.save() Commented Jan 15, 2017 at 11:17
0

You forgot to write new keyword, so do this :

var bookSchema = new mongoose.Schema({
    author : { type: mongoose.Schema.Types.ObjectId, ref: 'author' },
    genre: String,
});

Cheers:)

1
  • Strange, I defined all my models without new, and everything works. I wonder if there is a difference. P.S. adding it didn't solve the issue.
    – jeff
    Commented Jan 15, 2017 at 10:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.