MongoDB聚合:$存在的任何值

我试图利用MongoDB聚合RESTful api,但陷入了下面的情况。 假设我有Subscriptions模型,看起来像这样:

 var mongoose = require('mongoose'), Schema = mongoose.Schema; var SubscriptionSchema = new Schema({ // ... cancelled: Date }); 

如果订阅处于活动状态,则cancelled属性可以是undefined ,也可以是用户取消操作的Date

现在,我有一个GET /me/subscriptions ,它聚合了订阅,并有一个可选的查询参数: cancelled=true (只显示取消)或cancelled=false (只显示活动)。 如果没有指定,应该返回任何订阅(激活或取消)。

 var express = require('express'), router = express.Router(), Subscription = require('../../models/subscription'); router.get('/me/subscriptions', function(req, res, next) { var cancelled = req.query.cancelled === 'true' ? { $exists: true } : req.query.cancelled === 'false' ? { $exists: false } : { $exists: { $or: [ true, false ] } }; // wrong logic here return Subscription.aggregate([ { $match: { user: req.user._id, cancelled: cancelled }}, { $project: { // ... }} ]) .exec() // ... }); module.exports = router; 

如果我通过上面提到的查询参数,它会工作得很好,但如果没有指定参数(如果它不等于truefalse ),则无法find模型。 我已经尝试了很多东西,而不是错误的行(在$matchpipe道中):

 cancelled: {} cancelled: void 0 cancelled: { $exists: { $or: [ true, false ] } } cancelled: { $exists: { $in: [ true, false ] } } cancelled: { $exists: [ true, false ] } // obviously wrong, but hey cancelled: null // obviously wrong, too cancelled: { $or: [ { $exists: false }, { $exists: true } ] } // can't use $or here, but still, hey 

唯一的解决办法是现在看到的是这样的,比较一个值不是undefined而不是typesDate ,但它似乎太hacky。

 cancelled: { $ne: 'some-impossible-value' } 

很感谢任何forms的帮助。

我认为只要稍微调整就可以满足条件。

 var express = require('express'), router = express.Router(), Subscription = require('../../models/subscription'); router.get('/me/subscriptions', function(req, res, next) { var match_query = {user: req.user._id}; if (req.query.cancelled === 'true') { match_query.cancelled = {$exists:true}; } else if(req.query.cancelled === 'false') { match_query.cancelled = {$exists:false}; } return Subscription.aggregate([ { $match: match_query}, { $project: { // ... }} ]) .exec() // ... }); module.exports = router; 

你不需要添加{$ exists:{$或者:[true,false]},只要不添加任何东西来查询,如果你没有得到真或假。

我没有检查代码的语法错误,但逻辑上它会工作。

我将重构$matchpipe道,如下所示(需要安装momentjs库):

 router.get('/me/subscriptions', function(req, res, next) { var match = { "$match": { "user": req.user._id, "cancelled": {} } }; if (req.query.cancelled === 'true' || req.query.cancelled === 'false') { match["$match"]["cancelled"]["$exists"] = JSON.parse(req.query.cancelled); } else if(moment(req.query.cancelled, moment.ISO_8601, true).isValid()){ match["$match"]["cancelled"] = moment(req.query.cancelled).toDate(); } else { match["$match"]["cancelled"]["$exists"] = false; } return Subscription.aggregate([match, { "$project": { // ... }} ]).exec() // ... });