简体   繁体   English

在NodeJS中处理多个顺序依赖的mongo查询结果的最佳方法

[英]Best way to process results of multiple, sequential, dependent mongo queries in NodeJS

High level 高水平

I'm new to JS and Node. 我是JS和Node的新手。 I'm working on an API endpoint that should return a status value. 我正在开发一个应该返回状态值的API端点。 To compute the status value I need to make two sequential mongo queries where the second set of queries depend on the first query. 要计算状态值,我需要进行两个连续的mongo查询,其中第二组查询依赖于第一个查询。 The second set of queries will give me a status for each value found in the first query, of which I will pick one based on some logic. 第二组查询将为我提供第一个查询中找到的每个值的状态,我将根据某些逻辑选择一个。 What is the best way to do it in NodeJS? NodeJS中最好的方法是什么?

Specifics 细节

Here are parts of my first attempt. 这是我第一次尝试的部分内容。

function getItemStatus(key, value, callback) {
        MongoClient.connect(mongo_url, function(err, db) {
            if (err) { return console.dir(err); }
            db.collection('status', function(err, coll) {
                if (err) { return console.dir(err); }
                coll.distinct("_id.metric", function(err, metrics) {
                    if (err) { return console.dir(err); }
                    console.log('metrics : ', metrics);
                    _.foreach(metrics, function(metric) {
                        var query = {"_id": {
                            "$gte" : {key: key, value: value, created: new Date("1800-01-01T00:00:00"), metric : metric},
                            "$lte" : {key: key, value: value, created: new Date("2100-01-01T00:00:00"), metric : metric}}};
                        coll.find(query, {sort: {"_id.created": -1}, limit: 1})

I make a connection, query for a set of metric values using a distinct query. 我建立连接,使用不同的查询查询一组度量值。 For each metric I then want to ask for the latest status. 对于每个指标,我想要询问最新状态。 Ideally I'd like to have the entire set of statuses so that I could write a function taking this set and deciding on which status will be returned. 理想情况下,我希望拥有整套状态,以便我可以编写一个函数来获取此集合并决定返回哪个状态。 My problem is passing the statuses back "up the chain" so that I can process the set of statuses. 我的问题是将状态传递回“链上”,以便我可以处理这组状态。

In a synchronous situation I would simply write something like this 在同步的情况下,我只想写这样的东西

val metrics = getDistinctMetrics(key, value)
val statuses = metrics.map(getStatusForMetric)
val status = filterStatuses(statuses)

How can I accomplish this in JavaScript/NodeJS? 如何在JavaScript / NodeJS中完成此操作?

UPDATED to highlight the fact that the first queries will trigger several queries in the second step, ie one for each result found by the first query. 更新以突出显示第一个查询将在第二步中触发多个查询的事实,即对于第一个查询找到的每个结果一个查询。

As I understand your question you want to execute queries parallel or in a waterfall mode and do some logic on the final result. 据我所知,你想要以并行或瀑布模式执行查询,并对最终结果做一些逻辑。 You should look into a library allowing parallel/waterfall execution. 您应该查看允许并行/瀑布执行的库。 Like this 像这样

Waterfall: Waterfall 瀑布: 瀑布

    async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
        // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
});

Parallel: Parallel 平行: 平行

async.parallel({
    collectionOne: function (callback) {
        collectionOne.find(query, function (err, result) {
            if (err) {
                return handleError(res, err);
            }
            callback(null, result);
        })
    },
    collectionTwo: function (callback) {
        collectionTwo.find(query, function (err, result) {
            if (err) {
                return handleError(res, err);
            }
            callback(null, result);
        })
    },
    collectionThree: function (callback) {
        collectionThree.find(query, function (err, result) {
            if (err) {
                return handleError(res, err);
            }
            callback(null, result);
        })
    },
    collectionFour: function (callback) {
        collectionFour.find(query, function (err, result) {
            if (err) {
                return handleError(res, err);
            }
            callback(null, result);
        })
    },
}, function (err, results) {
    return res.status(200).json(results);
});

And in the final callback you can doo some logic or return response. 在最后的回调中,你可以做一些逻辑或返回响应。

In your sample code, you are making network calls inside another network calls, which can lead to callback hell which can lead to misbehave of queries, in order to overcome that, you can use promises . 在您的示例代码中,您正在另一个网络调用中进行网络调用,这可能导致回调地狱 ,这可能导致查询行为异常,为了克服这一点,您可以使用promises

This will help you in avoiding callback hell as well as your query will also be resolved. 这将帮助您避免回调地狱以及您的查询也将得到解决。

Sample code:- 示例代码: -

new Promise (function(resolve, reject){
      return db.collection.find(function).exec()
      .then(function(result_of_first_query){
            return db.collection.findOne(function).exec()   //in this yopu can user the result of first query
      }).then(function(result_of_second_query){
             resolve(result_of_second_query);
      })
})

You can add more queries with each .then 您可以为每个.then添加更多查询

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM