【问题标题】:MongoDB query multiple collections at onceMongoDB一次查询多个集合
【发布时间】:2011-09-24 01:22:47
【问题描述】:
users
{
 "_id":"12345",
 "admin":1
},
{
 "_id":"123456789",
 "admin":0
}

posts
{
 "content":"Some content",
 "owner_id":"12345",
 "via":"facebook"
},
{
 "content":"Some other content",
 "owner_id":"123456789",
 "via":"facebook"
}

这是我的 mongodb 中的一个示例。我想获取所有具有“via”属性等于“facebook”并由管理员(“admin”:1)发布的帖子。我不知道如何获取此查询。由于 mongodb 不是关系型数据库,所以无法进行连接操作。有什么解决办法?

【问题讨论】:

    标签: collections join mongodb


    【解决方案1】:

    执行多个查询或使用嵌入文档或查看“数据库引用”。

    【讨论】:

      【解决方案2】:

      尝试在 MongoDB 中加入会破坏使用 MongoDB 的目的。但是,您可以使用 DBref 并编写您的应用程序级代码(或库),以便它自动为您获取这些引用。

      或者您可以更改架构并使用embedded documents

      您的最终选择是保持原样并执行两个查询。

      【讨论】:

      • 如何为此编写两个查询?
      • Doctrine MongoDB ODM 是处理此类事情的一个不错的库。但是,它只允许您通过一层参考加入;您不能以任何程度的语法轻松在引用中填充引用中的引用。
      • 如何在 MongoJS 中使用普通的旧查询来实现这一点?
      • 您现在可以使用$lookup 加入
      • 对不起,但我只想说,“尝试使用没有 JOIN 概念的数据库违背了数据库的目的。完全” Mongo 添加了 $lookup 因为错误地假设这不是案子。嵌入式文档不是最佳答案,因为它们与它们应该等效的记录不同步,并且您最终会复制数据。
      【解决方案3】:

      一种解决方案:将 isAdmin: 0/1 标志添加到您的帖子收集文档中。

      其他解决方案:使用 DBrefs

      【讨论】:

        【解决方案4】:

        正如之前在 MongoDB 中提到的,你不能在集合之间加入。

        对于您的示例,解决方案可能是:

        var myCursor = db.users.find({admin:1});
        var user_id = myCursor.hasNext() ? myCursor.next() : null;
        db.posts.find({owner_id : user_id._id});
        

        请参阅参考手册 - 光标部分:http://es.docs.mongodb.org/manual/core/cursors/

        其他解决方案是将用户嵌入帖子集合中,但我认为对于大多数 Web 应用程序,用户集合出于安全原因需要独立。用户集合可能有角色、权限等。

        posts
        {
         "content":"Some content",
         "user":{"_id":"12345", "admin":1},
         "via":"facebook"
        },
        {
         "content":"Some other content",
         "user":{"_id":"123456789", "admin":0},
         "via":"facebook"
        }
        

        然后:

        db.posts.find({user.admin: 1 });
        

        【讨论】:

          【解决方案5】:

          这里是您问题的答案。

          db.getCollection('users').aggregate([
              {$match : {admin : 1}},
              {$lookup: {from: "posts",localField: "_id",foreignField: "owner_id",as: "posts"}},
              {$project : {
                      posts : { $filter : {input : "$posts"  , as : "post", cond : { $eq : ['$$post.via' , 'facebook'] } } },
                      admin : 1
          
                  }}
          
          ])
          

          或者您可以使用 mongodb 组选项。

          db.getCollection('users').aggregate([
              {$match : {admin : 1}},
              {$lookup: {from: "posts",localField: "_id",foreignField: "owner_id",as: "posts"}},
              {$unwind : "$posts"},
              {$match : {"posts.via":"facebook"}},
              { $group : {
                      _id : "$_id",
                      posts : {$push : "$posts"}
              }}
          ])
          

          【讨论】:

          【解决方案6】:

          您可以使用$lookup (multiple) 从多个集合中获取记录:

          例子:

          如果您有更多收藏(我这里有 3 个用于演示的收藏,您可以拥有 3 个以上)。我想从单个对象中的 3 个集合中获取数据:

          集合如下:

          db.doc1.find().pretty();

          {
              "_id" : ObjectId("5901a4c63541b7d5d3293766"),
              "firstName" : "shubham",
              "lastName" : "verma"
          }
          

          db.doc2.find().pretty();

          {
              "_id" : ObjectId("5901a5f83541b7d5d3293768"),
              "userId" : ObjectId("5901a4c63541b7d5d3293766"),
              "address" : "Gurgaon",
              "mob" : "9876543211"
          }
          

          db.doc3.find().pretty();

          {
              "_id" : ObjectId("5901b0f6d318b072ceea44fb"),
              "userId" : ObjectId("5901a4c63541b7d5d3293766"),
              "fbURLs" : "http://www.facebook.com",
              "twitterURLs" : "http://www.twitter.com"
          }
          

          现在您的查询将如下所示:

          db.doc1.aggregate([
              { $match: { _id: ObjectId("5901a4c63541b7d5d3293766") } },
              {
                  $lookup:
                  {
                      from: "doc2",
                      localField: "_id",
                      foreignField: "userId",
                      as: "address"
                  }
              },
              {
                  $unwind: "$address"
              },
              {
                  $project: {
                      __v: 0,
                      "address.__v": 0,
                      "address._id": 0,
                      "address.userId": 0,
                      "address.mob": 0
                  }
              },
              {
                  $lookup:
                  {
                      from: "doc3",
                      localField: "_id",
                      foreignField: "userId",
                      as: "social"
                  }
              },
              {
                  $unwind: "$social"
              },
          
            {   
              $project: {      
                     __v: 0,      
                     "social.__v": 0,      
                     "social._id": 0,      
                     "social.userId": 0
                 }
           }
          
          ]).pretty();
          

          那么您的结果将是:

          {
              "_id" : ObjectId("5901a4c63541b7d5d3293766"),
              "firstName" : "shubham",
              "lastName" : "verma",
          
              "address" : {
                  "address" : "Gurgaon"
              },
              "social" : {
                  "fbURLs" : "http://www.facebook.com",
                  "twitterURLs" : "http://www.twitter.com"
              }
          }
          

          如果您想要每个集合中的所有记录,那么您应该从查询中删除以下行:

          {
                      $project: {
                          __v: 0,
                          "address.__v": 0,
                          "address._id": 0,
                          "address.userId": 0,
                          "address.mob": 0
                      }
                  }
          
          {   
                  $project: {      
                         "social.__v": 0,      
                         "social._id": 0,      
                         "social.userId": 0
                     }
               }
          

          删除以上代码后,总记录如下:

          {
              "_id" : ObjectId("5901a4c63541b7d5d3293766"),
              "firstName" : "shubham",
              "lastName" : "verma",
              "address" : {
                  "_id" : ObjectId("5901a5f83541b7d5d3293768"),
                  "userId" : ObjectId("5901a4c63541b7d5d3293766"),
                  "address" : "Gurgaon",
                  "mob" : "9876543211"
              },
              "social" : {
                  "_id" : ObjectId("5901b0f6d318b072ceea44fb"),
                  "userId" : ObjectId("5901a4c63541b7d5d3293766"),
                  "fbURLs" : "http://www.facebook.com",
                  "twitterURLs" : "http://www.twitter.com"
              }
          }
          

          【讨论】:

          • 嗨,@Shubham Verma,如何从“社交”或“地址”集合中获取多条记录。在同一个查询中。就像我在单个用户的社交收藏中有多条记录
          猜你喜欢
          • 2020-07-17
          • 2019-05-09
          • 1970-01-01
          • 2012-05-11
          • 2019-01-06
          • 1970-01-01
          • 2019-03-17
          • 2017-06-14
          相关资源
          最近更新 更多