Mongodb / Mongoose查询
User
有一堆Essays
,作为一个ObjectIds数组存储。 在CoffeeScript中,模式是:
User = new Schema essays: [Schema.Types.ObjectId] name: String Essay = new Schema grade: Number text: String author: Schema.Types.ObjectId
如何在一个查询中获得最近一篇文章写在最后一天, 最近一篇文章的评分在80到90之间的所有不同用户?
我有这个(在CoffeeScript中):
req.mongoose.Essay .find( _id: $gt: # trick which creates an ObjectId with yesterday's timestamp mongoose.Types.ObjectId.createFromHexString( (~~(yesterday.getTime() / 1000)).toString(16) + "0000000000000000" ) ) .where("grade").gt(80).lt(90) .popluate(path: "User") .exec (err, docs) -> console.log ({name: essay.author.name} for essay in docs)
这是接近但不完全。
这将会得到任何人在最后一天写的文章,其中文章的分数在80-90之间。 举个例子,如果两小时前我写了一篇文章,打了一个85分,但是一小时前写了一篇文章,打了50分,我就出现了 – 但是我不应该因为我最近的一篇文章 (写在最后一天)没有在80-90之间得分。
而且,如果有人在最后一天写了两篇文章,而且两篇文章都得到了85分,那么这将会重复。 请注意, distinct
function不能在同一个字段上populate
。
这个查询太宽泛了。 我需要得到每个人的最新论文 (必须写在最后一天)在80-90之间。
我能想到的唯一方法是通过查询User
集合来形成所有最后Essay
_id
的数组:
req.mongoose.User .find(essays: $not: $size: 0) # Just to be sure .select(essays: $slice: -1) # We only interested in last Essay .lean() # It's faster .exec (err, users) -> ids = users.map ({essays}) -> # essays array contains exactly one [last] element essays[0] .filter (_id) -> # We only interested in yesterday Essays _id.getTimestamp() >= yesterday req.mongoose.Essay .find(_id: $in ids) .where('grade').gt(80).lt(90) .popluate('User') .exec (err, docs) -> console.log ({name: essay.author.name} for essay in docs)
请注意,它还允许我使用ObjectId::getTimestamp
方法正确过滤提取的ids
以便将它们的生成date与yesterday
date进行比较。