web-dev-qa-db-ja.com

findメソッドからMongooseの結果を返す方法は?

ページをマングースの結果でレンディングするために見つけることができるものはすべて、このようにすることを言っています:

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
});

これはできますか?

55
MrBojangles

同期パラダイムを強制しようとしています。うまくいきません。 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
});
67
Josh

ネクロマンサーをここでプレイします。まだ別のより良い方法があります。

素晴らしいpromiseライブラリを使用する Bluebird およびその promisifyAll() メソッド:

_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);
_

すべてのmongoose(およびそのモデル)メソッドを、Async接尾辞(.exec().execAsync()になるなど)を使用して、promiseを返す関数として使用できるようにします。 .promisifyAll()メソッドはNode.JSの世界ではほぼ普遍的です-コールバックを最後の引数として取得する非同期関数を提供するものなら何でも使用できます。

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

.props() bluebirdメソッドは、プロパティとしてpromiseを持つオブジェクトを受け取り、両方のデータベースクエリ(ここではpromise)が結果を返すときに解決される集合的なpromiseを返します。解決された値は、最終関数のresultsオブジェクトです。

  • _results.users_-mongooseによってデータベースで見つかったユーザー
  • _results.articles_-mongoose(d'uh)がデータベースで見つけた記事

ご覧のとおり、インデントコールバックヘルに近づいていません。両方のデータベースクエリは並行して実行されます-どちらか一方が他方を待つ必要はありません。コードは短くて読みやすい-質問自体に投稿された希望的な「非動作例」に長さと複雑さ(またはむしろ欠如)で実際に対応しています。

約束はクールです。それらを使用します。

20
bardzusny

簡単な方法:

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 libraryのようなものを使用する必要があります。

しかし、あなたの場合、最も簡単な方法はコールバックをネストすることです(これにより、選択した以前のユーザーの記事を調べることができます)か、非同期ライブラリの助けを借りて完全に並行して行うことができます( フロー制御/非同期グッズ を参照してください)。

16
Oleg Shparber

Node関数への戻り値としてかなり使用する関数があります。

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

次に、すべての署名にオプションのコールバックパラメーターがあります。

1
Joe

私は非常に似たものを扱っていましたが、クライアントからsocket.ioとDBアクセスを使用していました。私の発見は、データベースがデータを取得する機会を得る前に、私のデータベースの内容をクライアントに投げ返すことでした。

DBを取得するための私の機能:

//ボードを読む-完全なデータベース

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);
        });
    });

したがって、この問題を解決するために、mongooseが提供する約束を使用し、DBからデータを受信すると、ソケットがクライアントにデータを送信します...

その価値のために...

1
Sten Muchow

次のコードで目的の結果を達成します。これがお役に立てば幸いです。

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);
});
1
Surender Singh