2014-04-11 4 views
0

내가 다른 사람의 사이에서,이 분야가, 문서가 있다고 가정 : 예를 들어MongoDB의 쿼리

{ 
    "class" : String, 
    "type" : String, 
    "name" : String, 
} 

을, 많은 같은 :

{ 
    "class": "class A", 
    "type": "type 1", 
    "Name": "ObjectA1" 
} 

{ 
    "class": "class A", 
    "type": "type 2", 
    "Name": "ObjectA2_1" 
} 

{ 
    "class": "class A", 
    "type": "type 2", 
    "Name": "ObjectA2_2" 
} 

{ 
    "class": "class B ", 
    "type": "type 3", 
    "Name": "ObjectB3" 
} 

는 내가 원하는 것은입니다 다음 구조를 반환하는 쿼리

{ 
    "class A" : { 
     "type 1" : ["ObjectA1"], 
     "type 2" : ["ObjectA2_1", "ObjectA2_2"] 
    }, 
    "class B" : { 
     "type 3" : ["ObjectB3"] 
    } 
} 

나는 aggr egate with $ group하지만 이것을 할 수는 없습니다. 이견있는 사람?

추신 : 나는 mongoose shell이나 mongoose와 같은 것이 아니고 이런 일을하고 싶습니다.

답변

1

집계 프레임 워크를 사용할 때의 문제점은 개체의 속성에 임의의 키 이름을 지정할 수 없다는 것입니다. 가능한 모든 키 이름을 지정할 수 없으면이를 사용하여 재 형성 할 수 없습니다.

그래서 같은 mapReduce 당신이 자바 스크립트에서 뭔가를 작동해야 결과를 얻을 수 있습니다 : 다음 감속기

var mapper = function() { 

    var key = this["class"]; 
    delete this._id; 
    delete this["class"]; 

    emit(key, this); 

}; 

:

var reducer = function (key, values) { 

    var reducedObj = {}; 

    values.forEach(function(value) { 
    if (!reducedObj.hasOwnProperty(value.type)) 
     reducedObj[value.type] = []; 

    reducedObj[value.type].push(value.Name); 

    }); 

    return reducedObj; 
}; 

첫째는 매퍼 정의를 그리고 당신은 (적어도 당신의 견본에서) 단지 1 개의 키 값 y로 매퍼에서 방출 될 수있는 아이템을 가지고 있기 때문에

db.collection.mapReduce(
    mapper, 
    reducer, 
    { "out": { "inline": 1 }, "finalize": finalize } 
) 

을 그리고 그 다음 출력을 제공합니다 : 결과를 포맷하는 동안

"results" : [ 
      { 
        "_id" : "class A", 
        "value" : { 
          "type 1" : [ 
            "ObjectA1" 
          ], 
          "type 2" : [ 
            "ObjectA2_1", 
            "ObjectA2_2" 
          ] 
        } 
      }, 
      { 
        "_id" : "class B ", 
        "value" : { 
          "type" : "type 3", 
          "Name" : "ObjectB3" 
        } 
      } 
    ], 

을 다음과 같이 그런 다음 맵리 듀스 함수를 호출

var finalize = function (key,value) { 

    if (value.hasOwnProperty("name")) { 
     value[value.type] = value.name; 
     delete value.type; 
     delete value.name; 
    } 

    return value; 
}; 

: OU도 마무리 기능이 필요합니다 매우 mapReduce 방식으로, 그것은 당신의 결과와 확실히 동일합니다.

var mapper2 = function() { 
    emit(null, this); 
}; 

그리고 다른 감속기 :

var reducer2 = function (key,values) { 

    reducedObj = {}; 

    values.forEach(function(value) { 
    reducedObj[value._id] = value.value; 
    }); 

    return reducedObj; 

}; 

하는 것은 다음과 같이 실행

다른 매퍼 정의 : 당신이 정말 더 먹고 싶어 않은 경우

는하지만, 당신은 항상 다음과 같은 작업을 수행 할 수 새지도로 출력되는 첫 번째 mapReduce :

db.collection.mapReduce(
    mapper, 
    reducer, 
    { "out": { "replace": "newcollection" }, "finalize": finalize } 
) 
새 컬렉션에 두 번째 맵리 듀스로 이어

:

db.newcollection.mapReduce(
    mapper2, 
    reducer2, 
    { "out": { "inline": 1 } } 
) 

그리고 당신의 결과가 :

"results" : [ 
      { 
        "_id" : null, 
        "value" : { 
          "class A" : { 
            "type 1" : [ 
              "ObjectA1" 
            ], 
            "type 2" : [ 
              "ObjectA2_1", 
              "ObjectA2_2" 
            ] 
          }, 
          "class B " : { 
            "type" : "type 3", 
            "Name" : "ObjectB3" 
          } 
        } 
      } 
    ], 
0

는 내가 필요로 무엇에 대한 해결 방법을 찾았. 그것은 동일하지 않지만 내 문제를 해결합니다. 오타가있을 수 있도록

{ 
    _id : "class A", 
    types: [ 
     { 
      type: "type 1", 
      items: ["ObjectA1"] 
     }, 
     { 
      type: "type 2", 
      items: ["ObjectA2_1", "ObjectA2_2"] 
     } 
    ] 
}, 
{ 
    _id : "class B", 
    types: [ 
     { 
      type: "type 3", 
      items: ["ObjectB3"] 
     } 
    ] 
} 

모두 코드 예를 여기에 기록 된 :

db.myDb.aggregate(
{ 
    $group:{ 
     _id: { 
      class_name : "$class", 
      type_name : "$name" 
     }, 
     items: { 
      $addToSet : "$name" 
     } 
    } 
}, 
{ 
    $group:{ 
     _id : "$_id.class_name", 
     types : { 
      $addToSet : { 
       type : "$_id.type_name", 
       items : "$items" 
      } 
     } 
    } 
}) 

나에게 뭔가를 주었다.

그래서 이것에 관한 내용입니다. 나는 그의 멋진 답변과 헌신을 위해 #Neil Lunn에게 감사 드리고 싶습니다.

마르셀