
스키마 검증, 필드 오타 디버깅, 혹은 설정되어서는 안 되는 필드를 찾으려면 MongoDB 컬렉션에 어떤 키들이 존재하는지 전체적으로 파악해야 합니다.
ObjectRocket을 비롯한 많은 MongoDB 관리형 서비스(DBaaS) 업체는 UI에서 손쉽게 이 작업을 수행할 수 있는 기능을 제공합니다. 또한 숙련된 MongoDB 사용자라면 대개 Mongoose(Node.js용)나 Mongoengine(Python용) 같은 ODM(Object-Document Mapper)을 먼저 도입해 애플리케이션에 일관된 스키마를 적용하고 오타 발생을 줄입니다. ODM은 타입 검증까지 수행해 주기 때문에, 정수 필드에 실수로 문자열을 넣어 연산 오류가 생기는 상황도 예방할 수 있습니다.
하지만 별도의 서비스나 ODM 없이 키 목록을 확인해야 한다면 몇 가지 다른 방법을 활용할 수 있습니다. 상황별로 MongoDB 컬렉션의 모든 키를 조회하는 가장 효과적인 방법들을 소개합니다.
예시 데이터
db.activities.insert( { type : ['indoor', 'outdoor', 'mixed'] } );
db.activities.insert( { activity : 'cycling' } );
db.activities.insert( { activity : 'skiing', location: 'Alpes' } );
db.activities.insert( { equipment : ['paddles', 'sunglasses'] } );여기서 얻고자 하는 고유 키는 다음과 같습니다.
type, activity, equipment, location
MapReduce 활용
MapReduce를 사용하면 다음과 같이 처리할 수 있습니다.
mr = db.runCommand({ "mapreduce" : "activities", "map" : function() { for (var key in this) { emit(key, null); } }, "reduce" : function(key, stuff) { return null; }, "out": "activities" + "_keys" })작업이 완료되면 결과 컬렉션에 distinct 명령을 실행해 모든 키를 찾습니다.
db.activities_keys.distinct("_id")하위 문서(subdocument)의 고유 키 목록이 필요하다면 해당 라인만 수정하면 됩니다.
for (var key in this.first_level.second_level.nth_level) { emit(key, null); }애그리게이션(Aggregation) 활용
애그리게이션 프레임워크를 지원하는 모든 드라이버에서 이 방법을 사용할 수 있습니다. 오버헤드를 줄이려면 $sample 또는 $limit 스테이지를 함께 활용하세요.
참고: primary 읽기 설정(read preference)으로 실행하면 성능에 영향을 줄 수 있으므로, secondary 읽기 설정으로 실행하는 것을 권장합니다.
버전 3.4.4 이상에서 제공되는 $objectToArray를 사용하면 최상위 키·값 쌍을 문서 배열로 변환할 수 있습니다. 여기에 $unwind와 $addToSet을 포함한 $group을 조합하면 컬렉션 전체에서 고유 키를 추출할 수 있습니다.
$$ROOT는 최상위 문서를 참조할 때 사용합니다.
db.activities.aggregate([ {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}}, {"$unwind":"$arrayofkeyvalue"}, {"$group":{"_id":null,"allkeys":{"$addToSet":"$arrayofkeyvalue.k"}}} ])단일 문서의 키 조회
애그리게이션으로 단일 문서의 키를 얻을 수도 있습니다.
db.activities.aggregate([ {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}}, {"$project":{"keys":"$arrayofkeyvalue.k"}} ])Mongo 셸
mongo 셸 클라이언트에서 아래 코드를 실행해 볼 수도 있습니다.
var allKeys = {}; db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})}); allKeys;단일 문서의 출력 필드 확인
컬렉션 내 특정 단일 문서의 필드만 출력해야 하는 경우(다른 문서들은 완전히 다른 키를 가질 수 있음)에는 다음을 사용하세요.
doc=db.thinks.findOne(); for (key in doc) print(key);Python
Python을 사용할 수도 있습니다. 아래 코드는 컬렉션의 모든 최상위 키 집합(set)을 반환합니다.
# pymongo와 'db'라는 이름의 연결 객체 사용
reduce(
lambda all_keys, rec_keys: all_keys | set(rec_keys),
map(lambda d: d.keys(), db.things.find()),
set()
)JavaScript
JavaScript로도 구현할 수 있습니다.
db.collection('collectionName').mapReduce(
function() { for (var key in this) { emit(key, null); } },
function(key, stuff) { return null; },
{ "out": "allFieldNames" },
function(err, results) {
var fields = db.collection('allFieldNames').distinct('_id');
fields
.then(function(data) {
var finalData = { "status": "success", "fields": data };
res.send(finalData);
delteCollection(db, 'allFieldNames');
})
.catch(function(err) {
res.send(err);
delteCollection(db, 'allFieldNames');
});
});새로 생성된 "allFieldNames" 컬렉션을 읽은 후에는 반드시 삭제합니다.
db.collection("allFieldNames").remove({}, function (err,result) {
db.close();
return;
});다양한 선택지
이처럼 Mongo 키를 조회하는 방법은 매우 다양합니다! MongoDB 관리가 부담스럽고 데이터베이스 운영보다 코드 개발에 집중하고 싶다면 저희가 도와드리겠습니다. 데이터베이스 플랫폼과 프리미엄 화이트글러브 지원 서비스를 무료로 경험해 보세요.