查询子文档时 Mongoose .find() 为空

Mongoose .find() is empty when querying on subdocument

我正在尝试根据其子文档数据查询文档。当我这样做时,我没有返回任何数据。当我删除 "where" 或查询 parent 中的原始类型字段时,它工作正常。我错过了什么?

我的 collections 被分解成单独的文件,为了简单起见,它们放在一起:

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);
    });

再一次,如果我以任何方式查询子文档,它 returns 一个空数据集。我试过 game.datePlayed 甚至 games.datePlayed。我不知道该怎么办。我不需要 player.firstName 结果,但我认为这很容易测试以确保查询设置正确。

最后,这是我设置日期范围的方式。日期 objects 正确显示,但它们可能是错误的类型吗?

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);

MongoDB 不支持联接,这正是您想要做的。您可以获得的最接近的是作为 .populate 调用的一部分进行过滤:

.populate('game', null, {datePlayed: {$gte: startDateRange, $lt: endDateRange}})
.populate('player', null, {firstName: 'Brian'})

然而,这样做的目的是获取 all GamePlayer 文档,并且只获取符合您条件的 Game 和 Player 子文档。如果子文档不符合您的条件,GamePlayer 文档仍将 return 编辑为 .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);
    });

以上示例将包括每个 returned 游戏中的所有玩家,无论他们的位置是否为 1,但它仅包括至少有一名玩家位置为 1 的游戏。

如果你想限制玩家数组中的项目,你可能需要更进一步,使用聚合命令展开数组然后过滤。例如:

GameModel.aggregate([
    {$unwind: 'players'},
    {$match: {'players.place' : 1}}

], function(err, results) {
    if (err) return next(err);
    res.json(results);
});

这将为每个位置为 1 的玩家 return 一个单独的游戏对象。如果一个游戏有多个位置为 1 的玩家,它将 return 复制游戏对象,每个都有不同的播放器。