2017-04-26 36 views
0

我有一個集合將玩家的名稱存儲爲字段,並將對手的名稱和回合作爲嵌入文檔進行播放。如何通過字段名稱返回按順序嵌入的文檔

"player1" : { "player2": 10,"player3": 25,"player4":8,"player5": 12} 

這意味着,播放"player1" 10輪與player2,25輪與player3,8輪與player4和12輪與player5

最終,我想查詢與特定玩家打最多回合的前3名對手。我想要得到他們的名字和回合,並在回合中以降序排列。

所以對於player1我想回"player3":25, "player5":12,"player2":10

現在最接近我走這麼遠就是做db.collection.distinct("player1"),它將返回我一個數組,其中嵌入的文件位於同一順序:

[ { "player2": 10,"player3": 25,"player4":8,"player5": 12} ] 

回答

1

您可以使用3.4.4版本並使用$objectToArray & $arrayToObject在動態鍵和標籤值對之間切換。

這是一種在不改變結構的情況下達到目標的方法。

階段1到3:將動態鍵轉換爲鍵值對,然後在player1上轉換$match

階段4至7:項目playeropponent並使用$objectToArray到動態對手鍵轉換成關鍵值對隨後$unwind + $sort + $limit

階段8 & 9:將opponent分組回密鑰值對的數組,然後按$arrayToObject將密鑰值對轉換爲動態密鑰。

db.collection.aggregate([ 
{$project: {keyvalarr: {$objectToArray: "$$ROOT"} }}, 
{$unwind:"$keyvalarr"}, 
{$match:{"keyvalarr.k":"player1"}}, 
{$project:{player:"$keyvalarr.k", opponent: {$objectToArray: "$keyvalarr.v"}}, 
{$unwind:"$opponent"}, 
{$sort:{"opponent.v":-1}}, 
{$limit:3}, 
{$group:{_id:null, player:{$first:"$player"}, opponent:{$push:"$opponent"}}}, 
{$project:{result: {$arrayToObject:"$opponent"}}} 
]) 

你必須改變你的結構爲類似下面的低版本,你可以使用索引。 (首選)

{player:"player1", opponent: [{player:"player2", rounds: 10},{player:"player3", rounds: 25}, {player:"player4", rounds: 8}, {player:"player5", rounds: 12}]} 

您可以簡化爲以下聚合管道。

db.collection.aggregate([ 
{$match:{"player":"player1"}}, 
{$unwind:"$opponent"}, 
{$sort:{"opponent.rounds":-1}}, 
{$limit:3}, 
{$group:{_id:null, player:{$first:"$player"}, opponent:{$push:"$opponent"}}} 
]) 
相關問題