我正在尝试对games
的概念进行建模,teams
players
players
在MongoDB中相互竞争。
我有两个集合:games
和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,
}
]
}
]
}
中的文档的样子。
db.games.find( { "teams.players.player._id": "2" } )
这是任务:给定一个玩家ID我想找到这个玩家参与的所有游戏。
我尝试了什么:
playerSchema = Schema
player: { type: Schema.ObjectId, ref: 'Player' }
score: { type: Number }
teamSchema = Schema
players: [ playerSchema ]
gameSchema = Schema
teams: [ teamSchema ]
但是,这不会返回任何内容。
顺便说一下,我正在使用以下架构的Mongoose:
Game.find 'teams.players.player._id': playerId
使用以下CoffeeScript查询:
{{1}}
,不会返回任何玩家ID的结果。
答案 0 :(得分:11)
在您的文件中:
"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
部分)。
答案 1 :(得分:1)
我使用您的反馈将此示例限制为主场和客队。请记住,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) {
});