【问题标题】:mongoose / MEAN.js - model.find() returns empty array if filteredmongoose / MEAN.js - 如果过滤,model.find() 返回空数组
【发布时间】:2015-02-07 16:30:53
【问题描述】:

我是 mean.js 的新手,所以它可能只是语法错误,但是当我使用 model.find() 和内部查询时 (option.find({poll_id:1}) 它返回一个空数组。

poll.server.model.js

'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

/**
 * Poll Schema
 */
var PollSchema = new Schema({
    poll_id: {type:Number},
    user_id: {type:Number},
    poll_question: {type:String},
    poll_language: {type:String},
    poll_description: {type:String},
    poll_description_raw: {type:String},
    poll_weight_additional: {type:Number},
    poll_flag_active:{type:Number,default:1},
    poll_flag_18plus:{type:Number,default:0},
    poll_flag_expire:{type:Number,default:0},
    poll_flag_deleted:{type:Number,default:0},
    poll_flag_moderated:{type:Number,default:0},
    poll_flag_favourised:{type:Number,default:0},
    poll_date_expiration:{type:Date},
    poll_date_inserted:{type:Date,default:Date.now()},
    poll_flag_updated:{type:Date},
    show_thumbs:{type:Number},
    comments:{
        type: Schema.ObjectId,
        ref: 'User'
    }
});

mongoose.model('Poll', PollSchema);

option.server.model.js

'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

/**
 * Option Schema
 */
var OptionSchema = new Schema({
    option_id:{type:Number},
    poll_id:{type:Number},
    option:{type:Number}
});

mongoose.model('Option', OptionSchema);

polls.server.controller.js

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    errorHandler = require('./errors.server.controller'),
    Poll = mongoose.model('Poll'),
    Option = mongoose.model('Option'),
    _ = require('lodash');

/**
 * List of Polls
 */
exports.list = function(req, res) {
    Poll.find().limit(10).sort('_id')/*.populate('user', 'displayName')*/.exec(function(err, polls) {
        if (err) {

            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });

        } else {
            for (var i=0; i < polls.length; i++) {
                // this works, returns an array with 10 items
                Option.find().exec(function(err,docs){
                    console.log(docs); 
                });
                // this doesnt! although i see in the former array that there are options
                // with the poll_id set to 1.
                Option.find({'poll_id':1}).exec(function(err,docs){
                    console.log(docs); 
                });

            }
            res.json(polls);
        }
    });
};

我做错了什么?我查了一下,但我没有看到任何提到我的问题的帖子。 我尝试使用带引号和不带引号的 model.find().where('poll_id').equals(1),但什么也没有。当我运行 model.find() 时,它可以工作,但无论我如何尝试过滤它,它都会返回一个空数组。提前感谢!

【问题讨论】:

  • 这是竞争条件的经典案例。控制器中的 for 循环与您的 res.json 调用并行执行,这意味着服务器在第一个循环执行完成之前响应客户端请求。您需要重组代码。我建议查看async 库。
  • 在这种情况下,您建议我如何重构我的代码?在回调中插入 res.json?对不起,我对此事的无知
  • 1) 永远不要为提出问题而道歉——它假设您在 SO 上提出问题是因为您正在学习。这个论坛上任何告诫你提问的人都没有抓住重点。 2) 你能用简单的英语写下你试图实现的查询吗?您的控制器中有几个“问题区域”,在我伸出援手之前,最好了解您的目标
  • 所以基本上我有一个页面,其中包含民意调查集合的民意调查列表。每个民意调查都有存储在另一个集合中的选项,即选项集合。选项集合中的每个文档都有 3 个字段,其中一个是 poll_id,它也是与此选项相关的投票的 id。所以,我希望投票列表中的每个投票都有一个选项数组,我需要通过属性 poll_id 检索它(这个项目是从 MySql 导入的,所以我现在不能使用属性 obeject._id)。非常感谢!

标签: javascript node.js mongodb mongoose mean-stack


【解决方案1】:

我了解您已从 MySQL 导入,但正确使用 Mongoose 存储和搜索数据的方法是使用 population 和 refs:

var Polls = mongoose.Schema({
  options: [{ type: Schema.Types.ObjectId, ref: 'Options' }]
});

var Options = mongoose.Schema({
  ...
});

Polls
  .find()
  .limit(10)
  .sort('_id')
  .populate('options')
  .exec(function (err, polls) {
    console.log(polls.options); // => [ array of options ]
  });

相关文档可以在这里找到http://mongoosejs.com/docs/populate.html

强烈建议您花一些时间重构您的数据,以便您可以利用填充和引用的许多优势(索引、更简洁的代码等)。不要犯试图在文档存储中强制使用关系范式的错误。彻底撕毁乐队助手或坚持你所知道的。

也就是说,您可以像这样使用当前数据实现您正在寻找的目标:

// npm install --save async
var async = require('async');

exports.list = function(req, res, next) {

  Poll.find().limit(10).sort('_id').exec(function (err, polls) {

    // In true HTTP parlance, the correct thing to do here would 
    // be to respond with a 500 instead of a 400. The error would
    // be coming from MongoDB, not a poorly formed request by the
    // client. Remember: 40Xs are for client errors and 50Xs are 
    // for server errors. If this is express, you should also look
    // into using a middleware error handler and passing the error 
    // down the line like so:
    if (err) return next(err);

    // Since you used a return statement above, there is no need for 
    // the if/else but this is a matter of style. If it helps with the
    // readability of your code, keep it. I choose to eliminate because
    // async code has enough nesting as it is!

    // https://github.com/caolan/async#maparr-iterator-callback
    async.map(polls, function (poll, callback) {

      // Now look up your option by its poll_id
      Option.find({'poll_id': poll.poll_id}, function (err, options) {
        if (err) return callback(err);
        poll.options = options;
        callback(null, poll);
      });

    }, function (err, data) {

      // Again, this would be a Mongo error, so pass it down the line to
      // handle as a generic 500.
      if (err) return next(err);

      // The data parameter is your newly mapped polls array
      res.json(data);

    });
  });
};    

请注意在没有人口和参考的情况下要实现多少样板。此外,在幕后人口只会击中数据库两次,而在这里你击中它 11 次。从长远来看,现在更改数据然后生成关系/文档存储混合体会更好。我见过它们,它们并不漂亮;)

【讨论】:

  • 我之所以接受这个答案,只是因为你基本上是对的,完全取下绷带!但解决方案没有奏效。我从那里走了很长一段路(或不那么长),但我又遇到了一个问题,在下一步。如果您想再次提供帮助 -> stackoverflow.com/questions/27464146/… :)
  • @DavidNelband 我很高兴你从答案中得到了一些东西。我不是 MEAN 堆栈开发人员,因为我无法忍受 Angular。 IMO 应该严格区分业务逻辑和模板。在那个回复中:像onclick="blah()" 这样的内联javascript 被认为是不好的做法,那么除了固有范围之外,ng-click="blah" 有什么区别?纳达。
猜你喜欢
  • 2021-10-22
  • 2020-08-11
  • 1970-01-01
  • 2016-06-28
  • 1970-01-01
  • 2021-06-05
  • 2013-12-17
  • 2015-08-16
相关资源
最近更新 更多