9

我试图在 MongoDB 中对彼此竞争的概念games进行teams建模players

我有两个系列:playersgames.

这就是文档的games外观。

{
    "_id": { "$oid": "1" },
    "teams": [
        {
            "players": [
                {
                    "player": { "$oid": "2" },
                    "score": 500,
                },
                {
                    "player": { "$oid": "3" },
                    "score": 550,
                }
            ]
        },
        {
            "players": [
                {
                    "player": { "$oid": "4" },
                    "score": 500,
                },
                {
                    "player": { "$oid": "5" },
                    "score": 550,
                }
            ]
        }
    ]
}

任务如下:给定一个玩家 ID,我想找到该玩家参与的所有游戏。

我试过的:

db.games.find( { "teams.players.player._id": "2" } )

但是,这不会返回任何内容。

顺便说一句,我正在使用具有以下架构的 Mongoose:

playerSchema = Schema
    player: { type: Schema.ObjectId, ref: 'Player' }
    score: { type: Number }

teamSchema = Schema
    players: [ playerSchema ]

gameSchema = Schema
    teams: [ teamSchema ]

使用以下 CoffeeScript 查询:

Game.find 'teams.players.player._id': playerId

它不会返回任何玩家 ID 的结果。

4

2 回答 2

12

在您的文档中:

"players": [
            {
                "player": { "$oid": "4" },
                "score": 500,
            },
            {
                "player": { "$oid": "5" },
                "score": 550,
            }
        ]

player嵌入式集合中的字段players是一个 BSON Id(即它看起来像ObjectId("4e208e070347a90001000008")),所以我认为您应该像这样构造您的查询:

db.games.find( { "teams.players.player": ObjectId("2") } )

请注意,我已经放弃了_id-- 前提是在 mongo 控制台中工作,然后我怀疑 Coffee 查询将是相似的(删除_id部分)。

于 2013-02-19T01:33:23.553 回答
2

我使用您的反馈将这个示例限制在主客队。请记住,Mongo 不是关系数据库,使用关系通常表明关系数据库的思维方式。复制是关键。

我没有从游戏中引用特定的玩家文档,而是存储了玩家的名字。我认为这是一个不可变的唯一索引。给玩家一个游戏数组,其中包含他玩过的每个游戏的引用。这实际上很糟糕,因为我们必须再次查询并填充这个数组。最好也在这里存储一个名称,但是由于我不知道您的情况,我不确定游戏是否具有不可变的可表示名称。

这个基本想法必须通过错误检查(例如中间件)来改进,但我把它留给你。

// Schemas
var playerSchema = new Schema({
    name: {type: String, index: true, unique: true},
    games: {type: [Schema.ObjectId], ref: 'Game'}
});

var gameSchema = new Schema({
    homeTeam: [{player: {name: String}, score: Number}]
    awayTeam: [{player: {name: String}, score: Number}]
});

// Models
var Player = mongoose.model('Player', playerSchema);
var Team = mongoose.model('Team', teamSchema);
var Game = mongoose.model('Game', gameSchema);

// Middleware
gameSchema.post('save', function (game) {
    var addMatchToPlayer = function(name) {
        Player.findOne({name: name}, function(err, player) {
            if (!err && player && player.games.indexOf(game._id) === -1) {
                player.games.push(game._id);
                player.save();
            }
        });
    }
    for (var i = 0; i < game.homeTeam.length; i++) {
        addMatchToPlayer(game.homeTeam[i].name);
    }
    for (var i = 0; i < game.awayTeam.length; i++) {
        addMatchToPlayer(game.awayTeam[i].name);
    }
});

// Queries
Player.findOne({name: 'Roel van Uden'}).populate('games').exec(function (err, player) {
});
于 2013-02-20T15:40:51.433 回答