【问题标题】:Use result from previous query in another query in mongodb在 mongodb 的另一个查询中使用上一个查询的结果
【发布时间】:2016-12-25 19:02:51
【问题描述】:

第一个查询:

    db.a.find({
    "type": ObjectId("50ed90f5a70defef23000002"),
    "config.name": "alpha"
 }, {
    "user": 1
 })

第一个查询结果:

{ "_id" : ObjectId("5684035c91b4693b39547591"), "user" : ObjectId("54ba80ac2735eea200623612") }

第二个查询:

   db.users.find({
    "_id": ObjectId("54ba80ac2735eea200623612")
}, {
    "lastname": 1
})

我可以将这两个查询合并为一个查询吗?第二个查询使用第一个查询结果的"user" 值ObjectId("54ba80ac2735eea200623612")

【问题讨论】:

  • 您可以将聚合管道与 $lookup 一起使用,但如果这是一种常见操作,则值得为您的给定用途重新建模您的文档。
  • @KevinSmith 听起来你更看重电力而不是数据,尽管数据在费用的可变指数中成倍增长。

标签: javascript mongodb


【解决方案1】:

您可以使用带有$match 的聚合来匹配您的条件,并使用$lookup 将您的本地字段user 映射到您的usercollection _id 字段:

db.a.aggregate(
    [{
        $match: {
            "type": ObjectId("50ed90f5a70defef23000002"),
            "config.name": "alpha"
        }
    }, {
        $lookup: {
            from: "users",
            localField: "user",
            foreignField: "_id",
            as: "users"
        }
    }, {
        $unwind: "$users"
    }]);

在 Javascript 中,例如使用mongoose,您可以使用:

YourModel.aggregate(
    [{
        $match: {
            "type": ObjectId("50ed90f5a70defef23000002"),
            "config.name": "alpha"
        }
    }, {
        $lookup: {
            from: "users",
            localField: "user",
            foreignField: "_id",
            as: "users"
        }
    }, {
        $unwind: "$users"
    }],
    function(err, result) {
        console.log("lastname : " + result.users.lastname);
    });

【讨论】:

    【解决方案2】:

    由于MongoDB doesn't support joins,不能将其合并为一个查询。

    您可以通过触发第一个查询、将结果存储在一个变量中然后使用它触发第二个查询来非常轻松地直接从 mongo shell 执行此操作。

    var userDoc = db.a.findOne({"type" : ObjectId("50ed90f5a70defef23000002"),"config.name":"alpha" },{"user":1});
    db.users.find({"_id" : userDoc.user},{"lastname":1})
    

    如果您的第一个查询返回多个结果,那么

    var cursor = db.a.find({"type" : ObjectId("50ed90f5a70defef23000002"),"config.name":"alpha" },{"user":1});
      cursor.forEach(function (userDoc) {
      var user = db.users.findOne({"_id" : userDoc.user},{"lastname":1});
      printjson(user);
    })
    

    注意:MongoDB 从 3.2 版本开始支持 left outer join using $lookup in aggregation pipeline

    但在这种情况下,这似乎有点过头了。

    【讨论】:

    • 请参阅@Bertrand Martel 的回答
    • userDoc.user 似乎不起作用,“无法规范化查询:BadValue 无法与未定义比较”
    • @timy:实际上find() 返回的是一个游标而不是实际的文档,所以如果只期望输出一个文档,findOne 会更合适。相应地更新了答案。
    • 这就是答案。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    相关资源
    最近更新 更多