将一个Mongoose查询的结果用于另一个

时间:2017-09-26 08:54:45

标签: node.js mongodb mongoose

我在Node中构建应用程序并使用Mongoose和CosmosDB。我想显示与登录用户关联的公司拥有的所有图表。

我有一个来自Passport.js的用户,我用它来查询数据库以便返回他的公司。返回正常。

我遇到麻烦的地方:一旦我有他的公司,我想再进行第二次查询以获得属于它的所有情节。这应该是带回一个对象数组,但它返回一个空数组。

两个问题:

  1. 如何使当前代码生效?
  2. 目前的结构非常尴尬 - 我如何让它更优雅?
  3. 代码:

       app.get('/plots',
            requireAuth,
            function(req, res) {
                let company;
                User.find({ email: req.user.email }).lean().exec(function(err, results) {
                    if (err) {
                        console.log(err);
                    }
                    if (!results) {
                        res.send(null);
                        return;
                    } else {
                        company = results[0].company;
                    };
                }).then(
                    PlotCast.find({ owner: company }).lean().exec(function(err, results) {
                        if (err) {
                            console.log('error', err);
                            res.send(err);
                        } else if (!results) {
                            res.send(null);
                        } else {
                            console.log('results', results);
                            res.send(results);
                        }
                    })
                ).catch(function(e) {
                    console.log('error', e);
                });
            }
        )
    

2 个答案:

答案 0 :(得分:2)

实际上为了让它更优雅你应该使用Promises,让我们说bluebird库(或任何其他首选的)

所以当你需要mongoose为它提供一个Promise库时,代码应该看起来更好,更具可读性和顺序性

const mongoose = require('mongoose');
const Promise = require('bluebird');
mongoose.Promise = Promise;

app.get('/plots', requireAuth,
        function(req, res) {
            User.find({ email: req.user.email }).lean()
                .then(function(results) {
                    if (!results) throw new Error('User not found');
                    else return results[0].company;
                })
                .then(function(company) {
                    return PlotCast.find({ owner: company }).lean();
                })
                .then(function(results) {
                    if (!results) throw new Error('Plot Cast not found')
                    else {
                        console.log('results', results);
                        res.send(results);
                    }
                })
                .catch(function(e) {
                    console.log('error', e);
                    res.status(400).send(e);
                });
        })

答案 1 :(得分:2)

有一个替代解决方案从来没有坏。

我个人讨厌直接与Promises合作,而更喜欢使用async.js。在您的情况下async.waterfall()会很有用,因为您基本上将结果从一个异步任务传递给下一个异步任务。

app.get('/plots', requireAuth, function(req, res) {
    async.waterfall([
        function getUser(done) {
            // use findOne, not find -- as you only want to retrive ONE user; using find is more expensive
            User.findOne({ email: req.user.email }).lean().exec(done);
        },
        function getCasts(user, done) {
            PlotCast.find({ owner: user.company }).lean().exec(done);
        },
    ], function (err, casts) {
        // if an error occurs during the above tasks ^, it will come down here
        if (err) {
            console.log(err);
            return res.status(400).send(e);
        }
        // otherwise if all tasks finish, it will come down here
        res.json(casts);
    });
});

因此,使用async.js的好处是,您可以将所有错误集中在一个地方,而不是拥有多个地方(根据您的工作情况,这也很好)。

我认为你最初的问题是你一起使用回调和承诺。通常你会使用其中一种。