MongoDB 집계 파이프라인에서 $replaceRoot 단계를 사용하면 배열 형태로 저장된 내장 문서(임베디드 도큐먼트)의 필드들을 상위 레벨로 끌어올리고, 동시에 키/값 구조를 원하는 형태로 변환할 수 있습니다.
$replaceRoot는 입력 문서 전체를 지정한 새 문서로 대체하는 역할을 합니다. 이때 _id 필드를 포함한 기존의 모든 필드가 새 문서의 내용으로 교체되므로, 기존 필드를 유지하고 싶다면 반드시 새 루트 문서에 명시적으로 포함시켜야 합니다.
샘플 데이터 생성하기
먼저 데모용 컬렉션을 만들고 문서를 삽입해 보겠습니다.
> db.demo733.insertOne(
... {
... "SubjectDetails":
... [
... {
... SubjectName:"MongoDB",
... "Marks":85
... },
... {
... SubjectName:"MySQL",
... "Marks":90
... },
... {
... SubjectName:"PL/SQL",
... "Marks":98
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5eac6e6156e85a39df5f6342")
}
find() 메서드를 사용해 컬렉션의 모든 문서를 조회합니다.
> db.demo733.find();
위 쿼리는 다음과 같은 결과를 출력합니다.
{ "_id" : ObjectId("5eac6e6156e85a39df5f6342"), "SubjectDetails" : [ { "SubjectName" : "MongoDB", "Marks" : 85 }, { "SubjectName" : "MySQL", "Marks" : 90 }, { "SubjectName" : "PL/SQL", "Marks" : 98 } ] }내장 문서 배열을 상위 레벨로 이동하는 쿼리
아래는 집계 파이프라인을 활용해 SubjectDetails 배열 안의 내장 문서들을 상위 레벨로 이동하고, 과목명을 키로, 점수를 값으로 갖도록 변환하는 쿼리입니다.
핵심 로직은 다음과 같습니다.
$map: 배열의 각 요소를 [키, 값] 쌍으로 변환합니다.$arrayToObject: 키/값 쌍의 배열을 하나의 객체로 변환합니다.$mergeObjects: 기존_id와 변환된 객체를 하나의 문서로 병합합니다.$replaceRoot: 병합된 최종 문서를 새 루트로 지정합니다.
> db.demo733.aggregate([
... {
... $replaceRoot: {
... newRoot: {
... $mergeObjects: [
... { _id: "$_id" },
... { $arrayToObject: { $map: { input: "$SubjectDetails", in: [ "$$this.SubjectName", "$$this.Marks" ] } } }
... ]
... }
... }
... }
... ]).pretty()
실행 결과는 다음과 같습니다. 각 과목 이름이 최상위 키가 되고, 점수가 해당 값으로 매핑된 것을 확인할 수 있습니다.
{
"_id" : ObjectId("5eac6e6156e85a39df5f6342"),
"MongoDB" : 85,
"MySQL" : 90,
"PL/SQL" : 98
}