2017-04-26 4 views
0

フィールドにプレーヤーの名前が格納され、対戦相手の名前とラウンドが埋め込みドキュメントとして再生されます。フィールド名で順序どおりの埋め込みドキュメントを返す方法

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

"player1"player5で、player3と、player2player4 12ラウンド8ラウンドを25ラウンド10ラウンドを果たしたことを意味します。

最後に、特定のプレイヤーで最も多くのラウンドを行った上位3名の相手に質問したいと思います。彼らの名前とラウンドを行い、ラウンドで降順にしたい。

のでplayer1のために、私は私がこれまで行ってきた最も近いdb.collection.distinct("player1")を行うと、それは私に埋め込まれた文書は同じ順序であるする配列を返しますで今"player3":25, "player5":12,"player2":10

を返したい:

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

答えて

1

3.4.4バージョンを使用し、$objectToArray & $arrayToObjectを使用すると、動的キーとラベル値のペアを切り替えることができます。

これは、構造を変更することなく、後の作業を達成する方法の1つです。

ステージ1〜3:ダイナミックキーをキー値のペアに変換し、次に$matchplayer1に変換します。

ステージ7を介して、4:プロジェクトplayeropponent$unwind + $sort + $limit続いてキー値ペアに動的相手キーを変換する$objectToArrayを使用します。

ステージ8 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"}}} 
]) 
関連する問題