mongodb-如何从find方法返回猫鼬结果?

我可以找到的用于渲染带有猫鼬结果的页面的所有内容都表示要这样做:

users.find({}, function(err, docs){
    res.render('profile/profile', {
        users:     docs
    });
});

我如何从查询中返回结果,更像这样?

var a_users = users.find({}); //non-working example

这样我就可以在页面上发布多个结果?

喜欢:

/* non working example */
var a_users    = users.find({});
var a_articles = articles.find({});

res.render('profile/profile', {
      users:    a_users
    , articles: a_articles
});

能做到吗?

MrBojangles asked 2019-11-15T04:42:15Z
6个解决方案
67 votes

您正在尝试强制执行同步范例。 就是行不通。 node.js是单线程的,大多数情况下-完成io后,就产生了执行上下文。 信令通过回调进行管理。 这意味着您具有嵌套的回调,命名函数或流控制库,以使外观更好看。

[https://github.com/caolan/async#parallel]

async.parallel([
   function(cb){
      users.find({}, cb);
   },
   function(cb){
      articles.find({}, cb);
   }
], function(results){
   // results contains both users and articles
});
Josh answered 2019-11-15T04:42:35Z
20 votes

我将在这里扮演死灵法师,因为我仍然看到另一种更好的方法。

使用精彩的承诺库Bluebird及其results.articles方法:

var Promise = require('bluebird');
var mongoose = require('mongoose');

Promise.promisifyAll(mongoose); // key part - promisification

var users, articles; // load mongoose models "users" and "articles" here

Promise.props({
    users: users.find().execAsync(),
    articles: articles.find().execAsync()
  })
  .then(function(results) {
    res.render('profile/profile', results);
  })
  .catch(function(err) {
    res.send(500); // oops - we're even handling errors!
  });

关键部分如下:

Promise.promisifyAll(mongoose);

使所有猫鼬(及其模型)方法都可作为返回promise的函数使用,后缀为results.articles.exec()变为.execAsync(),依此类推)。 .promisifyAll()方法在Node.JS世界中几乎是通用的-您可以在提供异步函数并将回调作为最后一个参数的任何东西上使用它。

Promise.props({
    users: users.find().execAsync(),
    articles: articles.find().execAsync()
  })

results.articles bluebird方法将带有promise的对象作为其属性,并返回在两个数据库查询(此处为promise)均返回其结果时已解决的集体promise。 解决的值是最终功能中的results.articles对象:

  • results.articles-猫鼬在数据库中找到的用户
  • results.articles-猫鼬(d'uh)在数据库中找到的文章

如您所见,我们甚至还没有缩进回调地狱。 这两个数据库查询都是并行执行的-不需要其中一个等待另一个。 代码简短易读-在长度和复杂度(或缺乏代码)上实际上与问题本身中发布的“不起作用的示例”相对应。

承诺很酷。 使用它们。

bardzusny answered 2019-11-15T04:43:58Z
16 votes

简单的方法:

var userModel = mongoose.model('users');
var articleModel = mongoose.model('articles');
userModel.find({}, function (err, db_users) {
  if(err) {/*error!!!*/}
  articleModel.find({}, function (err, db_articles) {
    if(err) {/*error!!!*/}
    res.render('profile/profile', {
       users: db_users,
       articles: db_articles
    });
  });
});

实际上,每个功能在Node.js中都是异步的。 猫鼬的发现也是如此。 如果要串行调用它,则应使用类似Slide库的东西。

但是在您的情况下,我认为最简单的方法是嵌套回调(这可以为以前选择的用户查询文章)或在异步库的帮助下完全并行执行(请参阅流控制/异步好东西)。

Oleg Shparber answered 2019-11-15T04:44:42Z
1 votes

我有一个函数,在返回Node函数时我经常使用它。

function freturn (value, callback){
    if(callback){
        return callback(value); 
    }
    return value; 
}; 

然后,我在所有签名中都有一个可选的回调参数。

Joe answered 2019-11-15T04:45:20Z
1 votes

我当时处理的是非常类似的事情,但使用的是来自客户端的socket.io和数据库访问。 我的发现是在数据库有机会获取数据之前将数据库的内容扔回客户端。因此,我将在这里分享我的发现:

我检索数据库的功能:

//阅读板-完整的数据库

var readBoards = function() {
        var callback = function() {
            return function(error, data) {
                if(error) {
                    console.log("Error: " + error);
                }
                console.log("Boards from Server (fct): " + data);

            }
        };

        return boards.find({}, callback());
    };

我的套接字事件监听器:

socket.on('getBoards', function() {
        var query = dbConnection.readBoards();
        var promise = query.exec();
        promise.addBack(function (err, boards) {
            if(err)
                console.log("Error: " + err);
            socket.emit('onGetBoards', boards);
        });
    });

因此,为了解决问题,我们使用猫鼬给我们的承诺,然后一旦我们从数据库接收到数据,我的套接字就会将其发送回客户端...

物有所值...

Sten Muchow answered 2019-11-15T04:46:21Z
1 votes

您可以通过以下代码获得所需的结果。 希望这会帮助你。

var async = require('async');

// custom imports
var User = require('../models/user');
var Article = require('../models/article');

var List1Objects = User.find({});
var List2Objects = Article.find({});
var resourcesStack = {
    usersList: List1Objects.exec.bind(List1Objects),
    articlesList: List2Objects.exec.bind(List2Objects),
};

async.parallel(resourcesStack, function (error, resultSet){
    if (error) {
        res.status(500).send(error);
        return;
    }
    res.render('home', resultSet);
});
Surender Singh answered 2019-11-15T04:46:46Z
translate from https://stackoverflow.com:/questions/6180896/how-to-return-mongoose-results-from-the-find-method