MongoDB查询对象数组中的对象数组

时间:2017-03-03 16:24:15

标签: mongodb mongoose mongodb-query aggregation-framework

我是mongoDB场景的新手,我正在尝试找出返回底层对象的最佳方法,该对象位于对象数组中包含的对象中。我知道这听起来令人困惑,所以让我告诉你我在做什么。

{
    "_id": ObjectId("58b833a04953db3dd302102b"),
    "team": "Dragons",
    "rosters": [{
        "season": "2016-17",
        "players": [{
            "pitcher": "Oliver queen"
        }, {
            "catcher": "Slade Wilson"
        }]
    }, {
        "season": "2015-16",
        "players": [{
            "pitcher": "Joker"
        }, {
            "catcher": "Batman"
        }]
    }]
}

所以我的最终目标是:

  1. 根据特定球队的特定赛季的位置(即“投手”)显示单个球员。例如,我想知道龙队的2015-16赛季投手是谁。

  2. 根据队伍的位置显示所有球员,为龙队提供所有赛季。

  3. 更新特定团队中特定团队的特定玩家的名称。 (例如,2016-17赛季“龙头队”从“奥利弗女王”到“绿箭”更新“投手”

  4. 这甚至是一个合理的查询构建?如果没有,我可以在哪里修复我的数据模型以提高性能?

    提前致谢。

1 个答案:

答案 0 :(得分:2)

您的集合中有多个嵌套数组,而在MongoDB中,您无法使用多个positional operator对您的播放器集合执行更新操作。您应该为玩家定义name字段和role字段。您可以按如下方式构建数据:

团队/季节文件

{
    "_id": ObjectId("58b99f08a7a2dfe1174e8eb9"),
    "team": "Dragons",
    "season": "2016-17",
    "players": [{
        "name": "Oliver queen",
        "role": "pitcher"
    }, {
        "name": "SomeOne",
        "role": "pitcher"
    }, {
        "name": "Slade Wilson",
        "role": "catcher"
    }]
}

因此,每个独特的团队/季节对都会有一个文档,所以:

  • 第一份文件:Dragons/2016-17
  • 第二份文件:Dragons/2015-17
  • 等...
  

根据他们的位置(即'投手')显示单个玩家   特定团队的特定季节。例如,我想知道谁   投手是2015-16赛季的龙队。

_如果你只有一个角色使用的玩家:

db.players.find({
    "team": "Dragons",
    "season": "2016-17",
    "players.role": "pitcher"
}, { "players.$": 1 })

它只返回匹配pitcher角色的第一个玩家:

{ "_id": ObjectId("58b99f08a7a2dfe1174e8eb9"), "players": [{ "name": "Oliver queen", "role": "pitcher" }] }

_如果您可以按角色拥有多个玩家(例如上面的模型中),请使用aggregation $filter players数组并使用匹配的角色:

db.players.aggregate([{
    $match: {
        "team": "Dragons",
        "season": "2016-17",
        "players.role": "pitcher"
    }
}, {
    $project: {
        players: {
            $filter: {
                input: "$players",
                as: "player",
                cond: { $eq: ["$$player.role", "pitcher"] }
            }
        }
    }
}])

这会给你:

{ "_id": ObjectId("58b99f08a7a2dfe1174e8eb9"), "players": [{ "name": "Oliver queen", "role": "pitcher" }, { "name": "SomeOne", "role": "pitcher" }] }
  

根据他们的位置显示所有球员的所有赛季   团队龙。

players.role使用汇总分组:

db.players.aggregate([{
    $match: {
        "team": "Dragons"
    }
}, {
    $unwind: "$players"
}, {
    $group: {
        _id: "$players.role",
        players: {
            $push: "$players.name"
        }
    }
}])

这给出了:

{ "_id": "catcher", "players": ["Slade Wilson", "Batman"] } { "_id": "pitcher", "players": ["Oliver queen", "SomeOne", "Joker"] }
  

更新特定季节中特定玩家的名称   特定的团队。 (例如,更新"投手"在2016-17赛季中   来自" Oliver Queen"到"绿箭"

使用匹配找到项目的positional parameter进行更新:

db.players.update({
    "team": "Dragons",
    "season": "2016-17",
    "players.name": "Oliver queen"
}, {
    $set: {
        "players.$.name": "Green Arrow"
    }
});

球队/赛季/球员文件

{
    "team": "Dragons",
    "season": "2016-17",
    "name": "Oliver queen",
    "role": "pitcher"
}, {
    "team": "Dragons",
    "season": "2016-17",
    "name": "SomeOne",
    "role": "pitcher"
}, {
    "team": "Dragons",
    "season": "2016-17",
    "name": "Slade Wilson",
    "role": "catcher"
}

每个文档都包含特定团队中特定团队中的玩家

  

根据他们的位置(即'投手')显示单个玩家   特定团队的特定季节。例如,我想知道谁   投手是2015-16赛季的龙队。

db.players.find({ "team": "Dragons", "season": "2016-17", "role": "pitcher" })
  

根据他们的位置显示所有球员的所有赛季   团队龙。

db.players.find({"team": "Dragons", "role": "pitcher"})
  

更新特定季节中特定玩家的名称   特定的团队。 (例如,更新"投手"在2016-17赛季中   来自" Oliver Queen"到"绿箭"

db.players.update({
    "team": "Dragons",
    "season": "2016-17",
    "name": "Oliver queen"
}, {
    $set: {
        "name": "Green Arrow"
    }
})