programing

MongoDB에서 내부 가입은 어떻게 하나요?

newstyles 2023. 7. 13. 20:43

MongoDB에서 내부 가입은 어떻게 하나요?

MongoDB에서 SQL inner join 같은 것을 할 수 있습니까?

나는 그것이 있다는 것을 압니다.$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에서 어떻게 관리할 수 있습니까?

나는 스스로 답을 찾았습니다.

$filind는 나에게 쿼리가 작동한 후 나에게 속임수를 썼습니다.

    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()

어쨌든 답변 감사합니다.

Tiramisu가 썼듯이 이것은 스키마 문제처럼 보입니다.

$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"
},

이것이 도움이 될까요?

const RolesSchema = new Schema({
  ....

});
const Roles = mongoose.model('Roles', RolesSchema);


const UserSchema = new Schema({
  ...

  roles: [{ type: mongoose.Schema.Types.ObjectId, ref: "Roles" }]
});

사용자 스키마의 채우기를 사용하여 중복성을 줄일 수도 있습니다.

당신 말이 맞아요$lookup속성은 SQL에서 외부 조인과 동일하지만 mongoDB에서는 유사한 작업을 수행하기 위해 추가 집계 단계가 필요합니다.INNER JOIN몽고로다음은 가입을 위한 예입니다.User그리고.ROLE에 기반한 컬렉션ID다음을 기준으로 결과를 표시USER_NAME그리고.ROLE_NAME

    db.User.aggregate([{
      $lookup: {
          from: "ROLE",
          localField: "ID",
          foreignField: "ID",
          as: "result"
        }
    },{
       $match: {
           result: {
             $ne: []
           }
        }
    },{
      $addFields: {
           result: {
             $arrayElemAt: ["$result",0]
           }
      }
    },{
       $project: {
          USER_NAME: "$USER_NAME",
          ROLE_NAME: "$result.ROLE_NAME"
       }
    }])

도움이 되길 바랍니다!!

MongoDB $lookup 집계는 이 질문에 가장 공식적이고 최적화된 방법입니다.그러나 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: y});
        }
        CollectionTwo.find(
            {$or: array}
        ).then((data1) => {
            res.status(200).json(data1);
        }).catch((error1) => {
            return error1;
        })
    }
}).catch((error0) => {
    return error0;
});

어레이를 사용했습니다.Push()방법과 그$orMongoDB의 운영자.사용할 수 있습니다.$nor연산자 대신 연산자$or외부 조인 문서를 찾습니다.또한 다음을 사용하여 찾기 알고리즘을 변경할 수 있습니다.$ne,$nor,$or,$and

총계 $206
동일한 데이터베이스에 있는 집합에 대한 왼쪽 외부 조인을 수행하여 처리를 위해 "가입된" 집합의 문서를 필터링합니다.$lookup 단계는 각 입력 문서에 새 배열 필드를 추가합니다.새 배열 필드에는 "가입된" 컬렉션의 일치하는 문서가 들어 있습니다.$lookup 단계는 이러한 재구성된 문서를 다음 단계로 전달합니다.

MongoDB 5.1부터는 $lookup이 여러 샤드 컬렉션에서 작동합니다.

서로 다른 두 컬렉션의 요소를 결합하려면 $union을 사용합니다.파이프라인 단계와 함께.


$lookup 단계의 구문은 다음과 같습니다.

조인 일치는 다음과 같습니다.
입력 문서의 필드와 "가입된" 컬렉션의 문서의 필드 간에 동등한 일치를 수행하려면 $lookup 단계에는 다음 구문이 있습니다.

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

자세한 정보: https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/

> 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"
...    }
... }])

언급URL : https://stackoverflow.com/questions/37575722/how-to-do-inner-joining-in-mongodb