猫鼬找到一个嵌套模型?

时间:2014-05-05 08:06:20

标签: node.js mongodb mongoose

以下是我的mongodb文档的概念(当然是json格式)

[
    {
        _id: 50, 
        team_name: 'bulls',
        players: [
            { 
                _id: 100, 
                player_name: 'Jokim'
            }
        ]
    }
] 

因此当路线api/teams/50/players/100点击时,我想要提供Jokim。我正在尝试阅读有关mongoose嵌套文档的其他帖子,但我似乎无法找到我在这里寻找的答案。我只是想找到这份文件,我已经有了路线设置。

models.Team.find({'players._id':req.params.id }, function(err, player) {
    if (err) {
        res.json({error: 'player not found.'});
    } else {
        res.json(player);
    }
});

这是我的SCHEMA

var Team = new Schema({
    team_name:   { type: String },
    players: [
        {
            player_name:  { type: String },
            points:       { type: Number },
            made_one:     { type: Number },
            made_two:     { type: Number },
            made_three:   { type: Number },
            missed_one:   { type: Number },
            missed_two:   { type: Number },
            missed_three: { type: Number },
            percentage:   { type: Number },
            assists:      { type: Number },
            rebounds:     { type: Number },
            steals:       { type: Number },
            blocks:       { type: Number },
            fouls:        { type: Number },  
            feed:         { type: String },
            facebook_id:  { type: Number }
        }
    ],
    points:       { type: Number },
    made_one:     { type: Number },
    made_two:     { type: Number },
    made_three:   { type: Number },
    missed_one:   { type: Number },
    missed_two:   { type: Number },
    missed_three: { type: Number },
    percentage:   { type: Number },
    assists:      { type: Number },
    rebounds:     { type: Number },
    steals:       { type: Number },
    blocks:       { type: Number },
    fouls:        { type: Number },  
    feed: { type: String }
});

2 个答案:

答案 0 :(得分:1)

因此,您正在寻找的方法可能使用aggregate方法。当然,您将从路线中提取team_idplayer_id值:

models.Team.aggregate(
    [
        // Makes sense to match the document
        { "$match": { 
            "_id": team_id,
            "players._id": player_id
        }},

        // Unwind the players array
        { "$unwind": "$players" },

        // Match the player only
        { "$match": { "players._id": player_id } },

        // Just project the player
        { "$project": { "_id": 0, "player": "$players" } }
    ],
    function(err,docs) {

       // do work here
    }
);

因此,虽然位置投影允许您投影作为父文档的一部分匹配的单个数组元素,但聚合管道中的投影形式允许您完全重新整形以在响应中包含匹配的数组元素

有关聚合的更多信息,请参阅手册中的operator reference

但是对于您提供的文档的基本示例:

db.teams.aggregate([
    { "$match": { 
        "_id": 50,
        "players._id": 100
    }},
    { "$unwind": "$players" },
    { "$match": { "players._id": 100 } },
    { "$project": { "_id": 0, "player": "$players" } }
])

给出结果:

{ "player" : { "_id" : 100, "player_name" : "Jokim" } }

答案 1 :(得分:1)

当您查询Team时,Mongoose返回的文档与您的架构具有相同的结构,因此您需要从该结构中提取您正在寻找的播放器。

使用$ positional projection operator标识您的查询中匹配的第一个玩家,以便您的结果仅包含players数组字段中的该玩家:

models.Team.findOne(
    {'players._id': req.params.id }, 
    {'players.$': 1}, 
    function(err, team) {
        if (err || !team || !team.players || !team.players.length) {
            res.json({error: 'player not found.'});
        } else {
            res.json(team.players[0]);
        }
    }
);

请注意,findOne代替find,因为您只想找到包含该播放器的单个团队。