2013-03-29 2 views
0

mongodb에서 필드 이름을 세기는 방법이 있습니까? 필자는 그 안에 다른 임베디드 문서가 포함 된 문서의 mongo 데이터베이스를 보유하고 있습니다. 다음은 데이터가 어떻게 보이는지 보여주는 예입니다.mongo 데이터베이스의 필드 이름 (값이 아님)을 계산합니다.

{ 
    "incident": "osint181", 
    "summary":"Something happened", 
    "actor": { 
     "internal": { 
      "motive": [ 
       "Financial" 
      ], 
     "notes": "", 
     "role": [ 
      "Malicious" 
     ], 
     "variety": [ 
      "Cashier" 
     ] 
     } 
    } 
} 

또 다른 문서는 다음과 같습니다

{ 
    "incident": "osint182", 
    "summary":"Something happened", 
    "actor": { 
     "external": { 
      "motive": [ 
       "Financial" 
      ], 
     "notes": "", 
     "role": [ 
      "Malicious" 
     ], 
     "variety": [ 
      "Hacker" 
     ] 
     } 
    } 
} 

당신이 볼 수 있듯이

는 배우가 두 번째 문서 외부에 내부에서 변경되었습니다. 제가 할 수 있기를 원하는 것은 배우의 각 유형에 대한 사건의 수를 세는 것입니다. 내 첫 번째 시도는 다음과 같이 보았다 :

db.public.aggregate({ $group : { _id : "$actor", count : { $sum : 1 }}}); 

그러나 그것은 나에게 전체 하위 문서를주고 카운트 많은 문서가 정확히 같은 얼마나 반영합니다. 오히려 나는 내부에 대한 카운트와 외부에 대한 카운트를 얻기를 바랬다. 우아한 방법이 있는가? 우아하지 않다면 누군가가 저에게 더러운 방법을 줄 수 있습니까?

답변

1

이것은 내가 Devesh의 힌트를 기반으로 생각한 대답이었습니다. 액터의 값을보고, 정의한 isEmptyObject 함수를 사용하여 문서가 빈 JSON 객체인지 확인하는 맵 함수를 만듭니다. 그런 다음 mapReduce를 사용하여 컬렉션을 살펴보고 작업 필드가 비어 있는지 확인합니다. 객체가 비어 있지 않으면 키의 값을 반환하지 않고 키 자체를 반환합니다. 키 자체는 내부 또는 외부 또는 다른 이름으로 반환됩니다.

여기의 마술은 mapReduce의 스코프 호출이었는데, 이는 내 isEmptyObject가 mapReduce의 범위에 있도록합니다. 결과는 temp라는 이름의 콜렉션에 기록됩니다. 임시 컬렉션에서 원하는 정보를 수집 한 후 삭제합니다.

var isEmptyObject = function(obj) { 
    for (var name in obj) { 
     return false; 
    } 
    return true; 
}; 

var mapFunction = function() { 
    if (isEmptyObject(this.action)) { 
     emit("Unknown",1); } 
    else { 
     for (var key in this.actor) { emit(key,1); } } }; 

var reduceFunction = function(inKeys,counter) { 
    return Array.sum(counter); }; 

db.public.mapReduce(mapFunction, reduceFunction, {out:"temp", scope:{isEmptyObject:isEmptyObject}}); 

foo = db.temp.aggregate(
    { $sort : { value : -1 }}); 

db.temp.drop(); 
printjson(foo) 
관련 문제