如何通过字段名称返回有序的嵌入式文档

时间:2017-04-26 00:36:43

标签: mongodb

我有一个收藏品将玩家的名字作为场地和他们的对手存储。名称和轮次作为嵌入文档播放。

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

这意味着"player1"使用player2进行了10轮,使用player3进行了25轮,使用player4进行了8轮,使用player5进行了12轮。

最终,我想查询与特定球员进行最多轮次的前三名对手。我希望得到他们的名字和轮次,然后按轮次降序排列。

因此,对于player1,我想返回"player3":25, "player5":12,"player2":10

现在我到目前为止最接近的是做db.collection.distinct("player1")并且它将返回一个数组,其中嵌入的文档的顺序相同:

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

1 个答案:

答案 0 :(得分:1)

您可以使用3.4.4版本并使用$objectToArray& $arrayToObject可在动态键和标签值对之间切换。

这是在不改变结构的情况下实现目标的一种方法。

第1阶段到第3阶段:将动态键转换为键值对,然后$match上的player1

第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"}}}
 ])