Mongoose和promises:如何获得一系列查询结果?

时间:2014-04-01 19:12:30

标签: node.js mongodb mongoose promise q

使用mongoose查询来自db和Q for promises的结果,但发现很难绕过只获取可用的用户列表。目前我有类似的东西:

var checkForPerson = function( person ) {
    people = mongoose.model('Person', Person)

    return people.findOne({"_id": person }, function(err, doc) {
        if (err) console.log(err)

        if (doc !== null) {
            return doc
        } else { 
            console.log('no results')
        }

    })
}

var promises = someArrayOfIds.map(checkForPerson);

// this is where I would like to have an array of models
var users = Q.all(promises)

//this fires off before the people.findOne query above to users is undefined
SomeOtherFunction( users )

我如何在SomeOtherFunction之前完成查询而不进行大量草率回调?

4 个答案:

答案 0 :(得分:19)

另一个建议是使用MongoDB的$in运算符将数组传递给find并有效地获得大量结果。每个都是一个Mongoose对象。

var promise = people.find({ _id: { $in: someArrayOfIds }).exec();
promise.then(function(arrayOfPeople) {
  // array of people ... do what you want here...
});

这比制作多个请求更有效,每个_id一个。

答案 1 :(得分:5)

“我如何继续承诺”这个问题的答案几乎总是与.then一致。它是;的承诺类比,它终止了一个异步语句。您可以在其中返回承诺,并在继续之前将其解包。

Q.all(promises).then(function(users){
    SomeOtherFunction(users);
});

或只是Q.all(promise).then(SomeOtherFunction)

您还需要findOne来实际返回承诺。您可以使用调用节点函数的Q.nfcallpromisify it yourself

Q.all所做的是接受一系列承诺,并在所有的时候完成,并在其中一个拒绝时拒绝。您可能希望在任何查询失败时附加.catch处理程序,或使用.done来表示链的结尾。像Bluebird这样的其他承诺库甚至会在没有.done或添加显式处理程序的情况下为您挑选错误,遗憾的是Q不会这样做。

答案 2 :(得分:4)

您也可以使用q(npm install q)

var q = require('q')
, aPromise = mongooseModelA.find({_id: aId}).exec()
, bPromise = mongooseModelB.find({_id: bId}).exec();

q.all([aPromise, bPromise]).then(function(bothA_and_B) {
  console.log(bothA_and_B);
});

答案 3 :(得分:0)

在这里可以使用Promise API:

import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib import colors as mcolors

width_dist = 10
depth_dist = 10
levels = 5

def bintree_level(levels, x, y, width):
    segments = []
    xl = x + depth_dist
    yl = y - width / 2
    xr = x + depth_dist
    yr = y + width / 2
    segments.append([[x, y], [xl, yl]])
    segments.append([[x, y], [xr, yr]])
    if levels > 1:
        segments += bintree_level(levels - 1, xl, yl, width / 2)
        segments += bintree_level(levels - 1, xr, yr, width  / 2)
    return segments

segs = bintree_level(levels, 0, 0, width_dist)

colors = [mcolors.to_rgba(c)
          for c in plt.rcParams['axes.prop_cycle'].by_key()['color']]
line_segments = LineCollection(segs, linewidths=1, colors=colors, linestyle='solid')

fig, ax = plt.subplots()
ax.set_xlim(-1, levels * depth_dist + 1)
ax.set_ylim(-1.5*width_dist, 1.5*width_dist)
ax.add_collection(line_segments)
plt.show()