2014-01-10 3 views
3

나는 몇 가지 '제품'개체가 :MongoDB : 배열 요소에서 일치 및 정렬 하시겠습니까?

{ name: 'ProductA', 
    social_stats: [ 
    { name: 'facebook', 
     shares: 60 
    }, 
    { name: 'twitter', 
     shares: 0 
    } 
    ] 
} 

{ name: 'ProductB', 
    social_stats: [ 
    { name: 'facebook', 
     shares: 0 
    }, 
    { name: 'twitter', 
     shares: 30 
    } 
    ] 
} 

난 항상 적어도 주에 대부분에서 분류 "트위터에서 가장 많이 공유 된 제품", "페이스 북에서 가장 많이 공유 된 제품"과, 쿼리 싶습니다. 내가 대신 내가 기대 '트위터'에 대해 동일한 쿼리를 실행할 때이 그러나, '올바른'이다

{ name: 'ProductA' } 
{ name: 'ProductB' } 

:

db.videos.find({ 
    _id: { 
    social_stats: { 
     $elemMatch: { 
     name: 'facebook' 
     } 
    } 
    } 
).sort({ 
    social_stats: { 
    shares: -1 
    } 
}) 

수익률 :

그래서 페이스 북에 대한 내 첫 번째 쿼리는 같은 보이는 B-> A와 동일한 출력을받습니다. & 정렬 논리를 함께 쓰지 않는 것처럼 보입니다. 즉, ''twitter '와 일치하는 social_stat 요소를 기준으로 주문하십시오.

나는 요소 social_stat 일치로 변경 내 쿼리 순서의 적용을 반영하기 위해()를 어떻게

  • 무엇을 찾고 있어요?
  • 이러한 일반적인 MongoDB 쿼리로는 불가능한 경우, 집계 프레임 워크로 수행 할 수있는 작업입니까? 그리고 그게 어떻게 생겼을까요?
  • 그런 다음 보너스로 Mongoid를 사용하여 동등한 쿼리를 작성하는 방법은 무엇입니까?

일부 관련 링크 내가 바라 보았다 :

답변

4

배열로 검색 결과를 sort() 수 없으므로 이후의 결과는 얻을 수 없습니다. '트위터'에 대한

db.videos.aggregate(
    // Optional: potentially take advantage of an index to only find videos with 
    //   facebook stats; could also limit to those with shares $gt 0 
    { $match: { 
     'social_stats.name' : 'facebook' 
    }}, 

    // Convert the social_stats array into a document stream 
    { $unwind: '$social_stats' }, 

    // Only match the social stats for facebook 
    { $match: { 
     'social_stats.name' : 'facebook' 
    }}, 

    // Sort in descending order 
    { $sort: { 
     'social_stats.shares' : -1 
    }}, 

    // Only include the product names & score 
    { $project: { 
     _id: 0, 
     name: "$name", 
     shares: "$social_stats.shares" 
    }} 
) 

결과 : '페이스 북'에 대한

{ 
    "result" : [ 
     { 
      "name" : "ProductB", 
      "shares" : 30 
     }, 
     { 
      "name" : "ProductA", 
      "shares" : 0 
     } 
    ], 
    "ok" : 1 
} 

결과 :

(MongoDB를 2.4에서와 같은)

가장 좋은 방법은 집계 프레임 워크를 사용하는 것

{ 
    "result" : [ 
     { 
      "name" : "ProductA", 
      "shares" : 60 
     }, 
     { 
      "name" : "ProductB", 
      "shares" : 0 
     } 
    ], 
    "ok" : 1 
} 
+0

이것은 몽고 이드로 번역하는 것이 간단해야하지만 [몽고이와 MongoDB 집계 프레임 워크] (http://blog.joshsoftware.com/2013/09/05/mongoid-and-the-mongodb-aggregation-framework/)는 도움이 될 시작입니다. – Stennie

+0

이것은 정확하게 내가 끝내었던 것이고, 집계 프레임 워크는 훌륭하게 일을 완수했다. Mongoid는 MongoDB 쿼리를 작업으로 변환하는 것이 매우 간단하기 때문에 실행할 명령 배열 ('[match, unwind, match, sort, project]')을 전달할 수있는'Model.collection.aggregate() 몽고이드와. –

1

입니다 배열 당신은 집계 프레임 워크 또는 MapReduce가 필요하다고 생각합니다.

.sort({"social_stats.facebook.shares" : -1}) 

참고 : 당신이

{ name: 'ProductB', 
    social_stats : { 
    'facebook' : {shares: 0, name : "Facebook"}, 
    'twitter' : {shares: 30, name : "Twitter"}, 
    } 
} 

에 구조를 변경한다면 ... 당신은 할 수이뿐만 아니라 변화를 쿼리가 필요합니다!

+0

거푸집 없음, 같은 결과. –

+0

맞아요, 나는'social_stats'가 임베디드 배열이라고 생각하지 않았습니다. 내 업데이트를 참조하십시오. – luttkens

+0

나는 이것이 훌륭한 해결책이라고 생각하지만 몽고이 (Mongoid)와 루비 (Ruby) 클래스가 얼마나 잘 작동하는지 잘 모르겠습니다. 특히'embeds_many' 관계를'field type : Hash'로 변경해야 호환이 가능해집니다. 확실히 실용적이지만, 유스 케이스에는 바람직하지 않을 수 있습니다. 모든 상향 투표의 가치가 있습니다. –