【问题标题】:Mongoose query fed into arrayMongoose 查询输入数组
【发布时间】:2015-11-20 12:06:05
【问题描述】:

我在处理这段代码时遇到了一些问题。 所以我使用 Mongoose 从我的数据库中获取数据,然后我想将其中的一部分数据推送到一个名为“authors”的数组中,然后单独使用该数据。

我可以访问数据,因为如果我使用 console.log() 对其进行了调试,但是我无法在 while 循环之外获取该数据。发生了什么事?

最后一行以 '[]' 响应

    while (i < 8) {
        var search = User.find({'twitter.id' : collected[i].author});

        search.exec(function (err, user){
            if (err) return console.error(err);

            var result = (user[0].twitter.username);
            authors.push(result);

        });

        i = i + 1;
    }

    console.log(authors);

【问题讨论】:

    标签: javascript node.js mongoose


    【解决方案1】:

    最后一行以 '[]' 响应

    这是因为User.find() 是一个async 调用。所以当你在i = 8时跳出循环,你会在数据返回之前点击console.log(authors)

    另一个问题

    当您只需要进行1 调用时,您似乎正在对数据库进行8 单独调用。如果您有一个名为 collected 的数组,您正在循环访问该数组。它看起来像这样。

    var collected = [
      { author : "23423423"},
      { author : "23423424"},
      { author : "23423425"},
      { author : "23423426"},
    ];
    

    您可以使用.map 函数收集所有推特 ID。

    var twitterIds = collected.map(function(a){return a.author});
    

    现在twitterIds == ["23423423", "23423424", "23423425", "23423426"]

    然后您可以使用$in 运算符选择twitter.id 的值等于指定数组中的任何值的文档。

    然后你可以这样做User.find({ "twitter.id" : {$in : twitterIds}});

    它将返回一个包含所有匹配文档的文档,然后您可以对其进行操作。现在您已经减少到1 呼叫而不是8

    用两个选项重构

    我会以两种方式之一重构代码:

    1) 返回查询

    function search(twitterIds){
       var query = User.find({ "twitter.id" : twitterIds});
       return query;
    }
    

    那么你就可以这样使用了:

    var searchQuery = search(twitterIds);
    searchQuery.exec(function(err,users){
      if(err) return console.log(err);
      //do something with users..
      users.forEach(function(user){
      console.log(user.twitter.username);// do something here
      });
    }
    

    2) 回报承诺

    function search(twitterIds){
       var promise = User.find({ "twitter.id" : twitterIds}).exec();
       return promise;
    }
    

    那么你就可以这样使用了:

    var promise = search(twitterIds);
    promise.then(function(users){
      //do something...
    }).error(function(err){
       console.log(errr);
    });
    

    在使用 async 库之前,我会从这里开始,看看这是否能完成工作。

    【讨论】:

    • 非常有趣!那么我怎么能等到我有数据再传递这些数据呢?
    • @gregjw 我会更新我的答案,但你为什么要把 find 放在循环中?
    • 我想我有一个奇怪的用例。所以我必须处理 8 个单独的请求。所以我有 8 张图片,对于每张图片,我想找到它的用户,然后我会将这两条数据都传递给我的视图。所以我不确定我是否可以针对该问题修改您的解决方案?
    • 好的。你试过第一个案例了吗?它起作用了吗?那么您使用什么标准来查找图像?
    • 确实如此。如果所有图像都有一位作者,它将返回一位用户。如果有两个作者,两个用户。但我需要区分每个图像附加了哪个用户。
    【解决方案2】:

    由于 Javascript 是异步的,即使循环仍在运行,console.log(authors) 也会被执行。

    要在js中处理异步,你可以使用这个async模块,它非常强大且易于使用。

    --- 编辑

    var _  = require('lodash');
    var authors;
    User.find({ "twitter.id" : {$in: _.map(collected, 'author')}}).exec()
    .then(function(docs) {
        author = docs;
        // Do something
    
    })
    

    我认为你可以这样做,与@inspired基本相同

    【讨论】:

    • 您能给我举个例子,说明在这种情况下如何使用异步模块吗?
    猜你喜欢
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 2014-05-13
    • 2016-03-24
    • 2016-01-24
    • 2018-06-12
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多