我试图根据其子文档数据查询文档。当我这样做时,我没有返回任何数据。当我删除"其中"或者当我查询父级中的原始类型字段时,它工作正常。我错过了什么?
我的馆藏被分解为单独的文件,为简单起见,它们在一起:
var PlayerSchema = new Schema({
firstName: { type: String, default: '', required: true},
lastName: { type: String, default: '', required: true},
nickname: { type: String, default: '' },
});
module.exports = mongoose.model('Player', PlayerSchema);
var GameSchema = new Schema({
winner: { type: Schema.Types.ObjectId, ref: 'Player', required: true},
datePlayed: { type: Date, default: Date.now, required: true },
});
module.exports = mongoose.model('Game', GameSchema);
var GamePlayerSchema = new Schema({
game: { type: Schema.Types.ObjectId, ref: 'Game', required: true},
player: { type: Schema.Types.ObjectId, ref: 'Player', required: true},
points: { type: Number, default: 0 },
place: { type: Number, default: 0 },
});
module.exports = mongoose.model('GamePlayer', GamePlayerSchema);
我的查询:
GamePlayerModel.find()
//.where('player.firstName').equals('Brian') // returns empty
//.where(place).equals(1) // returns correct dataset
.where('game.datePlayed').gte(startDateRange).lt(endDateRange) // returns empty
.select('game player points place')
.populate('game')
.populate('player')
.exec(function (err, gamePlayers) {
if(err) return next(err);
res.json(gamePlayers);
});
因此,如果我以任何方式查询子文档,它将返回一个空数据集。我已尝试game.datePlayed
甚至games.datePlayed
。我不知道该怎么做。我不需要player.firstName
结果,但我认为这是一件容易测试的事情,以确保查询设置正确。
最后,这就是我设置日期范围的方法。日期对象正确出来,但它们可能是错误的类型吗?
var now = new Date();
var month = req.query.month ? parseInt(req.query.month) : now.getUTCMonth();
var year = req.query.year ? parseInt(req.query.year) : now.getUTCFullYear();
var endMonth = month+1;
if(endMonth > 11) endMonth = 0;
var startDateRange = new Date(year, month, 1);
var endDateRange = new Date(year, endMonth, 1);
答案 0 :(得分:2)
MongoDB不支持联接,这正是您要做的。您最接近的是在.populate
电话中过滤:
.populate('game', null, {datePlayed: {$gte: startDateRange, $lt: endDateRange}})
.populate('player', null, {firstName: 'Brian'})
然而,这将是所有 GamePlayer文档,只获得符合您条件的游戏和玩家子文档。如果子文档不符合您的条件,则仍会返回GamePlayer文档,.game
或.player
等于null。
您可能希望重新考虑您的架构,使其不再像SQL架构,并利用MongoDB的优势。我不确定你的要求是什么,但请考虑这样的事情:
var PlayerSchema = new Schema({
firstName: { type: String, default: '', required: true},
lastName: { type: String, default: '', required: true},
nickname: { type: String, default: '' },
});
var GameSchema = new Schema({
winner: { type: Schema.Types.ObjectId, ref: 'Player', required: true},
datePlayed: { type: Date, default: Date.now, required: true },
players: [{
player: { type: Schema.Types.ObjectId, ref: 'Player', required: true},
points: { type: Number, default: 0 },
place: { type: Number, default: 0 }
}]
});
然后您的查询可能类似于:
GameModel.find()
.where('players.place').equals(1) // This will limit the result set to include only Games which have at least one Player with a place of 1
.where('datePlayed').gte(startDateRange).lt(endDateRange)
.populate('players.player')
.exec(function (err, games) {
if(err) return next(err);
res.json(games);
});
以上示例将包括每个返回游戏中的所有玩家,无论他们的位置是否为1,但是它将仅包含至少有一个位置为1的玩家的游戏。
如果要限制player数组中的项目,可能需要更进一步,并使用aggregate命令展开数组然后过滤。例如:
GameModel.aggregate([
{$unwind: 'players'},
{$match: {'players.place' : 1}}
], function(err, results) {
if (err) return next(err);
res.json(results);
});
这将为每个玩家返回一个单独的游戏对象,如果一个游戏有多个玩家的位置为1,它将返回重复的游戏对象,每个对象都有一个不同的玩家。