2014-02-09 79 views
2

假設我在MongoDB中有一個users集合。典型的用戶文檔包含一個名稱字段和一組代表用戶特徵的子文檔。說這樣的:MongoDB - 按子文檔匹配排序

{ 
    "name": "Joey", 
    "characteristics": [ 
     { 
      "name": "shy", 
      "score": 0.8 
     }, 
     { 
      "name": "funny", 
      "score": 0.6 
     }, 
     { 
      "name": "loving", 
      "score": 0.01 
     } 
    ] 
} 

我怎麼能找到最有趣的最有趣的用戶,按他們的有趣程度排序?

我到目前爲止發現的唯一辦法,是使用聚合框架,在類似這樣的查詢:

db.users.aggregate([ 
    {$project: {"_id": 1, "name": 1, "characteristics": 1, "_characteristics": '$characteristics'}}, 
    {$unwind: "$_characteristics"}, 
    {$match: {"_characteristics.name": "funny"}}, 
    {$sort: {"_characteristics.score": -1}}, 
    {$limit: 10} 
]); 

這似乎正是我想要的,根據這除了事實到MongoDB's documentation on using indexes in pipelines,一旦我在聚合管道中調用$project$unwind,我不能再使用索引來匹配或排序集合,這使得此解決方案對於非常大的集合而言是不可行的。

回答

1

我認爲你是在那裏的一半。我會做

db.users.aggregate([ 
    {$match: { 'characteristics.name': 'funny' }}, 
    {$unwind: '$characteristics'}, 
    {$match: {'characteristics.name': 'funny'}}, 
    {$project: {_id: 0, name: 1, 'characteristics.score': 1}}, 
    {$sort: { 'characteristics.score': 1 }}, 
    {$limit: 10} 
]) 
  • 我添加match階段擺脫用戶無需funny屬性(可以很容易地索引)。再次
  • unwindmatch,以保持數據的只有某一部分
  • 通過正確比分
  • limit結果只保留與project
  • sort必要的數據。

那樣你可以使用索引進行第一次匹配。

的方式我看它,如果你有興趣瞭解的特性並不太多,IMO倒不如讓你的結構

{ 
    "name": "Joey", 
    "shy": 0.8 
    "funny": 0.6 
    "loving": 0.01 
} 

這樣,你可以使用索引(稀疏或不)讓你的生活更輕鬆!

+0

究竟是我最終做了什麼:)謝謝重申雖然。關於第二個建議 - 不幸的是,索引有太多不同的「特徵」(MongoDB目前允許每個集合最多有64個不同的索引)。 – ozk