2013-08-06 3 views
0

피드가있는 컬렉션이 있습니다. 서류는 다음과 같이 구성되어 있습니다 : MongoDB (Node JS), 계산 된 필드를 전달 된 변수를 사용하는 쿼리 결과에 올바르게 추가하는 방법

{ 
    _id: '123', 
    title: 'my title', 
    openedBy: ['321', '432', '543'] // ID of users 
} 

은 그럼 사용자가 :

사용자가 가져온 피드를 열었다 친구의 수를 얻을 수 있습니다 내가 달성하고자하는
{ 
    _id '321', 
    friends: ['432'] // ID of users 
} 

. 나는 이제 mapReduce를 사용하여 피드를 가져 오는 사용자의 친구를 전달합니다. 나는 단지 그 자체를 방출 반환하여 줄로 내가 제대로하고있는 중이 야 생각하지 않는다 나는 종료 자에 일반 쿼리 결과에 결과를 다시 변환해야합니다 :

db.collection(collectionName).mapReduce(function() { 
     var openedByFriendsLength = 0; 
     for (var x = 0; x < friends.length; x++) { 
      if (this.openedBy.indexOf(friends[x]) >= 0) { 
       openedByFriendsLength++; 
      } 
     } 

     emit(this._id, { 
      title: this.title, 
      openedByLength: this.openedBy.length, 
      openedByFriendsLength: openedByFriendsLength 
     }); 
    }, function (key, emits) { 
     return emits[0]; 
    }, { 
     out: 'getFeeds', 
     scope: { 
      friends: user.friends 
     }, 
    }, function (err, collection) { 
     collection.find().toArray(function (err, feeds) { 
      // Convert the _id/value to a normal find result 
      var resultFeeds = []; 
      for (var x = 0; x < feeds.length; x++) { 
       resultFeeds.push(feeds[x].value); 
       resultFeeds[resultFeeds.length - 1]._id = feeds[x]._id; 
      } 
      callback(err, resultFeeds); 
     }); 
    }); 

나는 집계 살펴 보았다,하지만 난 똑같은 일을하는 방법을 알아낼 수 없습니다. 아니면 여기서 문서의 구조가 모두 잘못 되었습니까?

답장을 보내 주셔서 감사합니다.

답변

1

집계 프레임 워크를 사용하여 계산 방법을 문의하십시오. 일반적으로 집계 프레임 워크는 map-reduce보다 성능이 우수합니다. 집계 프레임 워크에 대한 문서는 http://docs.mongodb.org/manual/aggregation/에서 찾을 수 있습니다.

나는 주어진 사용자가 openBy 배열에 포함되어있는 모든 피드를 찾은 다음 해당 열어 본 배열에 포함 된 해당 사용자의 고유 친구 수를 찾는 것으로 알고 있습니다. 그게 맞습니까?

맵 - 감소와 같은 첫 번째 단계는, 예를 들어, 사용자의 컬렉션으로부터 사용자의 친구 목록을 얻을 정도로 응집, 단지, 한 번에 하나 개의 집합에서 동작

: 다음

friends = db.users.findOne({_id:user}).friends 

db.feeds.aggregate([ 
    {$match: {openedBy: user}}, 
    {$unwind: '$openedBy'}, 
    {$match: {openedBy: {$in: friends}}}, 
    {$group: {_id: '$openedBy'}}, 
    {$group: {_id: 0, count: {$sum: 1}}} 
]) 

가 집계 명령은 파이프 라인의 한 단계까지 문서의 스트림을 전달 유닉스 파이프 라인처럼 많은 일을 처리 단계의 목록을 지정합니다 : 우리는 계산을 수행 할 피드 모음에서 다음 집계를 수행 할 수 있습니다 다음.

  • 파이프 라인의 첫 번째 단계는 첫째, $ 매치는 모음 입력으로 모든 문서를 취하고 만 사용자가 openedBy 어레이에 포함되는 위치를 선택한다.

  • 두 번째 단계 인 $ unwind는 각 입력 문서를 가져 와서 여러 개의 출력 문서를 생성합니다. 하나는 openBy 배열의 각 멤버에 대해 하나는 출력 문서입니다. 각 출력. 서에는 값이 단일 사용자 인 openBy 필드가 들어 있습니다. 이들은 주어진 사용자와 동일한 피드를 연 사용자입니다. 이 단계는 나중에 파이프 라인의 단계가 열리는 By 배열의 개별 값에 대해 집계 연산을 수행 할 수있게합니다.

  • 세 번째 단계 인 $ match는 해당 사용자의 친구 인 opensBy 사용자가있는 문서 만 통과하도록 해당 문서를 필터링합니다. 그러나 주어진 친구는이 스트림에서 두 번 이상 표시 될 수 있으므로 중복을 제거하려면 집계가 필요합니다.

  • 네 번째 단계 인 $ group은 집계를 수행하여 openedBy 필드의 각 값에 대해 하나의 출력 문서를 생성합니다.이것은 사용자가 열어 놓은 피드를 열었던 주어진 사용자의 중복되지 않은 고유 한 친구 세트입니다. _id 필드는 친구 사용자 ID입니다.

  • 마지막 단계 인 $ 그룹은 이전 단계에서 생성 된 문서 수를 계산합니다. 여기에 원하는 값을 사용할 수있는 _id가 0 인 단일 문서와 계산하고자하는 최종 계산 수가 포함 된 개수 필드가있는 단일 문서를 출력합니다. 예 :

    { "result" [{ ""_id ": 0,"개수 ": 2}]"ok ": 1}

이 답변이 도움이되기를 바랍니다. 추가 질문이 있으면 알려주십시오.

브루스

관련 문제