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

时间:2015-04-09 12:02:28

标签: node.js mongodb mongoose nosql

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

我的馆藏被分解为单独的文件,为简单起见,它们在一起:

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

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,它将返回重复的游戏对象,每个对象都有一个不同的玩家。