네, 가능합니다. MongoDB에서 중첩(nested) 필드를 제외하려면 집계 파이프라인(aggregation pipeline)을 활용하는 것이 가장 효과적입니다. 일반적인 프로젝션(projection)으로는 이름이 동적인 하위 필드를 일괄 제외할 수 없지만, $objectToArray와 $arrayToObject 연산자를 조합하면 마치 와일드카드처럼 여러 중첩 필드를 한 번에 처리할 수 있습니다. 이 글에서는 그 과정을 단계별로 살펴보겠습니다.
1단계: 컬렉션 생성 및 문서 삽입
먼저 예제로 사용할 컬렉션을 만들고 문서를 삽입합니다. details 객체 안에 Info1, Info2라는 중첩 구조가 있는 것이 핵심입니다.
> db.demo413.insertOne(
... {
... "_id": "101",
... "details": {
... "Info1": {
... Name:"Chris",
... Age:21
... },
... "Info2": {
... Name:"David",
... Age:23
... }
... }
... }
... );
{ "acknowledged" : true, "insertedId" : "101" }
2단계: find() 메서드로 문서 조회
find() 메서드를 사용해 컬렉션의 모든 문서를 확인합니다.
> db.demo413.find();
실행 결과는 다음과 같습니다.
{ "_id" : "101", "details" : { "Info1" : { "Name" : "Chris", "Age" : 21 }, "Info2" : { "Name" : "David", "Age" : 23 } } }
3단계: 중첩 필드를 제외하는 쿼리 작성
다음은 details 내부의 모든 객체에서 Age 필드를 일괄 제외하는 쿼리입니다. 동작 원리는 세 단계로 나눌 수 있습니다.
$objectToArray: 객체를 키-값(k, v) 배열로 변환합니다.$project의 제외 조건(0): 변환된 배열에서v.Age값을 제거합니다.$arrayToObject: 배열을 다시 원래의 객체 형태로 복원합니다.
> db.demo413.aggregate([
... { $project: { "details" : { $objectToArray: "$details" } } },
... { $project: { "details.v.Age" : 0} },
... { $project: { "details" : { $arrayToObject: "$details"} } }
... ]);
쿼리를 실행하면 다음과 같이 각 Info 객체에서 Age 필드만 깔끔하게 제거된 결과를 얻을 수 있습니다.
{ "_id" : "101", "details" : { "Info1" : { "Name" : "Chris" }, "Info2" : { "Name" : "David" } } }
정리
필드 이름을 미리 알 수 없거나 Info1, Info2처럼 구조가 유사한 여러 중첩 객체를 한 번에 다뤄야 할 때, 위의 $objectToArray → 제외 → $arrayToObject 패턴은 와일드카드와 같은 역할을 합니다. MongoDB의 기본 프로젝션 문법으로는 동적 키를 지정할 수 없기 때문에, 이 집계 파이프라인 방식이 사실상 가장 널리 쓰이는 표준 해결책입니다.