MongoDB에서 배열 형태로 저장된 데이터를 객체(맵) 형태로 변환해야 하는 경우가 있습니다. 이럴 때 집계 파이프라인의 $map과 $arrayToObject 연산자를 함께 사용하면 손쉽게 처리할 수 있습니다.
테스트용 컬렉션 생성하기
먼저 예제로 사용할 문서가 포함된 컬렉션을 생성하겠습니다.
> db.demo398.insertOne({
... "details":[
... {
... "Name":"Chris",
... "Age":22
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e5e8cedfac4d418a017856c")
}저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.
> db.demo398.find();
실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e5e8cedfac4d418a017856c"), "details" : [ { "Name" : "Chris", "Age" : 22 } ] }현재 details 필드는 배열 안에 문서 객체가 들어 있는 구조입니다. 이제 이 배열을 Name 값을 키로 하는 맵 형태로 변환해 보겠습니다.
배열을 문서 맵으로 변환하는 쿼리
다음은 배열을 여러 속성을 가진 문서 맵으로 변환하는 집계 쿼리입니다.
> db.demo398.aggregate([
... {
... "$addFields": {
... "details": {
... "$arrayToObject": {
... "$map": {
... "input": "$details",
... "as": "out",
... "in": {
... "k": "$$out.Name",
... "v": "$$out"
... }
... }
... }
... }
... }
... }
... ])실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e5e8cedfac4d418a017856c"), "details" : { "Chris" : { "Name" : "Chris", "Age" : 22 } } }쿼리 동작 원리 살펴보기
이 쿼리는 세 가지 연산자가 유기적으로 동작하는 구조입니다.
$map: details 배열의 각 요소를 순회하면서 k(키)와 v(값) 쌍으로 재구성합니다. 여기서는 각 문서의 Name 필드 값이 키가 되고, 문서 전체가 값이 됩니다.
$arrayToObject: k/v 쌍의 배열을 실제 자바스크립트 객체와 같은 맵 형태로 변환합니다.
$addFields: 기존 details 필드를 변환된 결과로 덮어써 새로운 구조의 문서를 출력합니다.
최종 출력을 보면 details 필드가 배열에서 객체로 변경되었고, Chris라는 이름이 키로 사용된 것을 확인할 수 있습니다. 이 방식은 특정 필드 값을 기준으로 문서에 빠르게 접근하고 싶을 때 매우 유용하게 활용됩니다.