简体   繁体   中英

Mongoose error: Schema hasn't been registered for model when populate

I am trying to join two collections and being able to get the combined data. To do so using Mongoose, i am supposed to use the populate syntax to achieve that. I am receiving error that the Schema Schema hasn't been registered for 'User_Fb'. From my code, I have exported the models and required in my server.js but the error is still appearing. What have I done wrong?

feed_post.model.js

var mongoose = require('mongoose');
var conn_new_app     = mongoose.createConnection('mongodb://localhost/new_app');
var User_fb = require('../models/fb_db.model');

var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
    user_id:  { type: Schema.Types.ObjectId, ref: 'User_Fb' },
    content: String,
    location: String,
    image: [{ type : String }]
});

var Feed_Post = conn_new_app.model('Feed_Post', feed_postSchema);

module.exports = Feed_Post;

fb_db.model.js

var mongoose = require('mongoose');
var conn_new_app     = mongoose.createConnection('mongodb://localhost/new_app');
var Feed_Post = require('../models/feed_post.model');

var user_fb = new mongoose.Schema({
    name: String,
    location: String,
    fb_id: Number
});

var User_Fb = conn_new_app.model('User_Fb', user_fb);

module.exports = User_Fb;

server.js

var express = require('express'),

mongoose = require('mongoose'),
User = require('./app/models/user.model'),
Post = require('./app/models/post.model'),
Maptest = require('./app/models/maptest.model'),
Feed_Post = require('./app/models/feed_post.model'),
User_Fb = require('./app/models/fb_db.model'),

app = express();

app.get('/testget', function(req,res){
    Feed_Post.findOne().populate('user_id').exec(function(err, c) {
        if (err) { return console.log(err); }

        console.log(c.fk_user.userName);
    });
});

UPDATED from Pier-Luc Gendreau Answer's

fb_db.model.js

module.exports = function (connection) {
    var mongoose = require('mongoose');
    var Schema = mongoose.Schema;

    var user_fb = new mongoose.Schema({
        name: String,
        location: String,
        fb_id: Number
    });

    return connection.model('User_FB', user_fb);;
}

feed_post.model.js

module.exports = function (connection) {
    var mongoose = require('mongoose');
    var Schema = mongoose.Schema;

    var feed_postSchema = new Schema({
        user_id:  { type: Schema.Types.ObjectId, ref: 'User_Fb' },
        content: String,
        location: String,
        image: [{ type : String }]
    });

    return connection.model('Feed_Post', feed_postSchema);;
}

server.js

var express = require('express'),
app = express(),

mongoose = require('mongoose'),
conn_new_app = mongoose.createConnection('mongodb://localhost/new_app'),
User_Fb = require('./app/models/fb_db.model')(conn_new_app),
Feed_Post = require('./app/models/feed_post.model')(conn_new_app);

app.get('/testget', function(req,res){
    Feed_Post.find().populate('user_id').exec(function(err, res) {
        if (err) { return console.log(err); }
        console.log(res);
    });
});

这就是我要做的全部Customer.findOne({}).populate({ path: 'created_by', model: User })而不是这个Category.findOne({}).populate({'author'})

IF YOU (really) USE MULTIPLE mongoDB CONNECTIONS


I do realise that this is not the case for the OP, but if you genuinely use multiple connections you MUST provide the model when using .populate(), as mongoose will only "find" models on the same connection. ie where:

var db1 = mongoose.createConnection('mongodb://localhost:27017/gh3639');
var db2 = mongoose.createConnection('mongodb://localhost:27017/gh3639_2');
var userSchema = mongoose.Schema({
  "name": String,
  "email": String
});

var customerSchema = mongoose.Schema({
  "name" : { type: String },
  "email" : [ String ],
  "created_by" : { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
});

var User = db1.model('users', userSchema);
var Customer = db2.model('customers', customerSchema);

Correct:

Customer.findOne({}).populate('created_by', 'name email', User)

or

Customer.findOne({}).populate({ path: 'created_by', model: User })

Incorrect (produces "schema hasn't been registered for model" error):

Customer.findOne({}).populate('created_by');

The problem is that you are creating a new connection in each and every model, so you end up with a bunch of different connection objects. Even though they are pointing to the same database, mongoose models don't know about other connections. You should instead create the connection object in your main app and then pass it around.

server.js

var express = require('express');
var mongoose = require('mongoose');

var app = express();
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var Feed_Post = require('./app/models/feed_post.model')(conn_new_app);

app.get('/testget', function(req,res){
  Feed_Post.findOne().populate('user_id').exec(function(err, c) {
    if (err) { return console.log(err); }
    console.log(c.fk_user.userName);
  });
});

Then modify your models so they are actually a function:

feed_post.model.js

module.exports = function (connection) {
  var mongoose = require('mongoose');
  var Schema = mongoose.Schema;

  var feed_postSchema = new Schema({
    user_id:  { type: Schema.Types.ObjectId, ref: 'User_Fb' },
    content: String,
    location: String,
    image: [{ type : String }]
  });

  return connection.model('Feed_Post', feed_postSchema);;
}

Also, like Adrian mentions, you can use mongoose as a singleton. However, I do recommend using createConnection as you did because if you ever need a second connection, you won't have to refactor the connection code to your first database.

It looks like you are creating a different database connection for each model, which isolates the models from each other. Mongoose must assume this isolation, because they could exist on different databases or even database servers.

Try connecting once, and just calling mongoose.model() instead of connection.model() when defining your models. Mongoose is a singleton by default.

就我而言,这个问题是因为我没有将ref model包含到应用程序中。

You can get the field you want by using select

Example to get the email of the customer:

Customer.findOne({}).populate({ path: 'created_by', model: User, select: 'email' })

More Details in mongoose documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM