【问题标题】:Mongoose populate find array of ObjectIdMongoose 填充查找 ObjectId 数组
【发布时间】:2017-04-20 10:32:38
【问题描述】:

在使用 Mongoose 进行查找时,我正在尝试填充 ObjectIds 数组。

这里是models/comment.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// set up a mongoose model
var CommentSchema = new Schema({
    comment: {
        type: String,
        unique: false,
        required: true
    },
    date: { 
        type: Date, 
        default: new Date()
    },
});

module.exports = mongoose.model('Comment', CommentSchema);

这里是models/question.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Comment = require('./comment');


// set up a mongoose model
var QuestionSchema = new Schema({
    title: {
        type: String,
        unique: false,
        required: true
    },
    question: {
        type: String,
        required: true
    },
    plus: {
        type: Number,
        required: true,
        default: 0
    },
    minus: {
        type: Number,
        required: true,
        default: 0
    },
    date: { 
        type: Date, 
        default: new Date()
    },
    comments:[
        {type: Schema.Types.ObjectId, ref: 'Comment'}
    ]
});

module.exports = mongoose.model('Question', QuestionSchema);

这里是index.js

var express     = require('express');
var app         = express();
var request     = require('request-promise');
var bodyParser  = require('body-parser');
var morgan      = require('morgan');
var mongoose    = require('mongoose');
var passport      = require('passport');
var config      = require('./config/database'); // get db config file
var User        = require('./models/user'); // get the mongoose model
var Room        = require('./models/room'); // get the mongoose model
var Comment    = require('./models/comment'); // get the mongoose model
var Question    = require('./models/question'); // get the mongoose model
var port        = process.env.PORT || 5000;
var jwt         = require('jwt-simple');
var http        = require('http');
var io          = require('socket.io');
var server      = http.createServer(app);
var io          = io.listen(server);



// get our request parameters
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// log to console
app.use(morgan('dev'));

// Use the passport package in our application
app.use(passport.initialize());

// Set the port
app.set('port', port);

//App files located in /public
app.use(express.static(__dirname + '/public'));

// views is the directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

// The root url of the website serves the Angular app
app.get('/', function (request, response) {
  response.render('pages/index');
});

// connect to database
mongoose.connect(config.database);

// pass passport for configuration
require('./config/passport')(passport);

var roomService = require('./controllers/roomservice.js');
roomService.setup(io);

// connect the api routes under /api/*
app.use('/api', apiRoutes);

// Start the Express app
server.listen(app.get('port'), function () {
  console.log('Node app is running on port', app.get('port'));
});

这里是controllers/roomservice.js

function RoomService(){
    var socketio;
    var Comment = require('../models/comment'); // get the mongoose model
    var Question = require('../models/question'); // get the mongoose model
    var Room = require('../models/room'); // get the mongoose model

    function setup(io){
        socketio = io;
        socketio.on("connection", function(socket){
            socket.on('joinRoom', function(msg){
                console.log("joinRoom");
                socket.join(msg.room)
                Question.find({})
                    .exec(function(err, questions) {
                        for(var question in questions){
                            for(var comment in questions[question].comments){
                                questions[question].comments[comment] = Comment.find({ "_id": questions[question].comments[comment]});
                            }
                        }
                        socket.emit("listQuestions", questions)
                });
            });
            socket.on('addQuestion', function(msg){
                console.log("addQuestion");
                var question = new Question({
                    title: msg.title,
                    question: msg.question
                });
                // save the question
                question.save(function(err) {
                    if (err) throw err;
                    io.to(msg.room).emit("addQuestion", question);
                });
            });
            socket.on('addComment', function(msg){
                var comment = new Comment({
                    comment: msg.comment
                });
                // save the comment
                Question.findOne({_id: msg.question}, function(err, question){
                    if (err) throw err;
                    question.comments.push(comment);
                    question.save(function(err) {
                        if (err) throw err;
                        io.to(msg.room).emit("addComment", comment);
                        console.log(question);
                    });
                });
            });
            socket.on('addPlus', function(msg){
                // save the comment
                Question.findOne({_id: msg.question}, function(err, question){
                    if (err) throw err;
                    question.plus = question.plus + 1;
                    question.save(function(err) {
                        if (err) throw err;
                        io.to(msg.room).emit("addPlus", question);
                    });
                });
            });
            socket.on('addMinus', function(msg){
                // save the comment
                Question.findOne({_id: msg.question}, function(err, question){
                    if (err) throw err;
                    question.minus = question.minus + 1;
                    question.save(function(err) {
                        if (err) throw err;
                        io.to(msg.room).emit("addMinus", question);
                    });
                });
            });
        });
    }

    return{
        setup: setup
    }
}

module.exports = new RoomService();

我正在尝试在返回问题列表时填充 cmets 数组。我尝试使用 Mongoose 的填充方法,但它返回一个空的 cmets 数组。

Question.find({}).populate("comments")
                    .exec(function(err, questions) {

                        socket.emit("questions", questions)
                });

当我不使用填充方法时,我会得到这样的结果:

[{"title": "test", "comments": ["1253454", "654654747"]},
 {"title": "test", "comments": ["1253454", "654654747"]}]

但我想要这样的东西:

[{"title": "test", "comments": [{"comment": "test"}, {"comment": "test2"}]},
 {"title": "test", "comments": [{"comment": "test"}, {"comment": "test2"}]}]

我做错了什么?

【问题讨论】:

  • mongoose.model 部分,您是否也这样指定它:mongoose.model('Comment', CommentSchema);?这对于 QuestionSchema 中的 ref 部分很重要
  • 这也可能与您在 CommentSchema 之前声明 QuestionSchema 有关。 mongoose API 在 Schema 构造函数部分有一个 Notemongoosejs.com/docs/api.html#schema_Schema
  • 你能展示一下你是如何导出这两个schemas的吗?也许ref 没有获得用于导出架构的正确名称。
  • 是的,包含评论模型和问题模型的文件都有这些行:module.exports = mongoose.model('Comment', CommentSchema);module.exports = mongoose.model('Question', QuestionSchema);。我在 Question 模型之前包含 Comment 模型,如下所示:var Comment = require('../models/comment');var Question = require('../models/question');
  • @Servietsky 你搞定了吗?面临类似问题

标签: node.js mongodb mongoose nosql


【解决方案1】:

你的猫鼬版本是什么? 4.7.1 版本适合我:

import { connDb } from './base';
import { model, Schema, SchemaTypes, disconnect } from 'mongoose';

const Question = model<any>('Question', new Schema({
  title   : SchemaTypes.String,
  comments: [
    {
      type: SchemaTypes.ObjectId,
      ref : 'Comment',
    },
  ],
}))
const Comment  = model<any>('Comment', new Schema({
  comment: SchemaTypes.String,
}))

connDb().then(() => Promise.all([
  Comment.remove({}),
  Question.remove({}),
])).then(() => Comment.insertMany([
  {
    comment: 'hello',
  },
  {
    comment: 'world',
  }
])).then((data: any[]) => Question.insertMany([
  {
    title   : 'question',
    comments: data.map((item: any) => item._id),
  }
])).then(() => Question.find({}).populate('comments').exec()).then((d) => {
  console.log(JSON.stringify(d))
}).then(() => disconnect())

结果是:

+ ts-node ./src/__test__/pop_comment.ts
[{"_id":"5846322e69db6c1ec86ac5fd","__v":0,"title":"question","comments":[{"_id":"5846322e69db6c1ec86ac5fb","__v":0,"comment":"hello"},{"_id":"5846322e69db6c1ec86ac5fc","__v":0,"comment":"world"}]}]

【讨论】:

  • 我使用的是 Mongoose 4.7.0,我尝试使用 4.7.1,但得到了相同的结果。
  • @Servietsky 你能发布你的应用程序的完整代码吗?可能有问题
  • 我在问题中发布了完整的代码,我只是删除了使用 REST API 的部分。
猜你喜欢
  • 2021-03-03
  • 2021-08-25
  • 2021-01-02
  • 2016-05-09
  • 1970-01-01
  • 2019-01-31
  • 2019-04-12
  • 2014-12-05
  • 2019-07-28
相关资源
最近更新 更多