【问题标题】:How to do inner joining in MongoDB?如何在 MongoDB 中进行内部连接?
【发布时间】:2016-10-01 05:43:10
【问题描述】:

是否可以在 MongoDB 中进行 SQL 内连接之类的操作?

我知道聚合管道中有 $lookup 属性,它相当于 SQL 中的 外连接,但我想做类似于 内连接的事情.

我有三个需要合并在一起的集合:

// User Collection
db.User.find({});

// Output:
{
   ID : 1,
   USER_NAME : "John",
   password : "pass"
}
{

   ID : 2,
   USER_NAME : "Andrew",
   PASSWORD : "andrew"
}

// Role Collection
db.ROLE.find({});

// Output:
{
   ID : 1,
   ROLE_NAME : "admin"
},
{
    ID : 2,
    ROLE_NAME : "staff"
}

// USER_ROLE Collection
db.USER_ROLE.find({});

// Output:
{
   ID : 1,
   USER_ID : 1,
   ROLE_ID : 1
}

我有上述集合,我只想提取与用户及其各自角色匹配的文档,而不是所有文档。如何在 MongoDB 中进行管理?

【问题讨论】:

  • 如果内部连接很关键,请考虑嵌入数据。否则,您必须运行多个查询才能完全按照您想要的方式加入多个集合。
  • 将任何查询转换为 mongo 查询:stackoverflow.com/questions/68155715/…

标签: mongodb join nosql


【解决方案1】:

我自己找到了答案

$展开 以下查询对我有用

    db.USER.aggregate([{
            $lookup: {
                from: "USER_ROLE",
                localField: "ID",
                foreignField: "USER_ID",
                as: "userRole"
            }
        }, {
            $unwind: {
                path: "$userRole",
                preserveNullAndEmptyArrays: false
            }
        }, {
            $lookup: {
                from: "ROLE",
                localField: "userRole.ROLE_ID",
                foreignField: "ID",
                as: "role"
            }
        }, {
            $unwind: {
                path: "$role",
                preserveNullAndEmptyArrays: false
            }
        }, {
            $match: {
                "role.ROLE_NAME": "staff"
            }, {
                $project: {
                    USER_NAME: 1,
                    _id: 0
                }
            }
            ]).pretty()

谢谢你的回答

【讨论】:

    【解决方案2】:

    正如提拉米苏所写,这看起来像是架构问题。

    您可以通过删除 $lookup 返回空数组的文档来进行手动内连接。

    ....
    {$lookup... as myArray},
    {$match: {"myArray":{$ne:[]}}},
    {$lookup... as myArray2},
    {$match: {"myArray2":{$ne:[]}}},
    

    架构改变

    我个人会去更新架构,像这样:

    db.User.find({})
    {
       ID : 1,
       USER_NAME : "John",
       password : "pass"
       roles:[{ID : 1,  ROLE_NAME : "admin"}]
    }
    
    
    db.ROLE.find({})
    {
       ID : 1,
       ROLE_NAME : "admin"
    },
    

    【讨论】:

    • 感谢 profesor79 的回答,但它是映射嵌入方式的好方法吗我有
    • 如果您担心数据冗余,请选择关系数据库。 NoSql 方法有利于非规范化数据。
    【解决方案3】:

    这有帮助吗

    const RolesSchema = new Schema({
      ....
    
    });
    const Roles = mongoose.model('Roles', RolesSchema);
    
    
    const UserSchema = new Schema({
      ...
    
      roles: [{ type: mongoose.Schema.Types.ObjectId, ref: "Roles" }]
    });
    

    在用户模式上使用populate,您还可以减少冗余

    【讨论】:

      【解决方案4】:

      如果你使用 Node.js 作为服务器端,那么你可以使用如下的小技巧。

      CollectionOne.find().then((data0) => {
          if (data0.length > 0) {
              let array = [];
              for (let i = 0; i < data0.length; i++) {
                  let x = data0[i]
                  let y = x.yourForeignKey;
                  array.push({_id: d});
              }
              CollectionTwo.find(
                  {$or: array}
              ).then((data1) => {
                  res.status(200).json(data1);
              }).catch((error1) => {
                  return error1;
              })
          }
      }).catch((error0) => {
          return error0;
      });
      

      我们使用了 Array Push() 方法以及 MongoDB 的 $or 运算符。您可以使用$nor 运算符而不是$or 来查找外连接文档。您还可以使用$ne$nor$or$and 等更改查找算法。

      【讨论】:

        【解决方案5】:
        > show dbs
        admin   0.000GB
        config  0.000GB
        local   0.002GB
        > use local
        switched to db local
        > show collections
        startup_log
        test1
        test2
        > db.test2.aggregate([{
        ...    $lookup: {
        ...       from: "test1",
        ...       localField: "id",
        ...       foreignField: "id",
        ...       as: "aggTest"
        ...    }
        ... }])
        

        【讨论】:

          猜你喜欢
          • 2023-02-10
          • 2018-06-16
          • 2019-03-22
          • 2011-03-18
          • 1970-01-01
          • 1970-01-01
          • 2019-02-06
          • 2017-09-03
          • 1970-01-01
          相关资源
          最近更新 更多