返回日期范围内的数组文档

时间:2017-06-15 18:39:25

标签: node.js mongodb mongoose aggregation-framework

是否可以在猫鼬中链接finById()select()find()?我正在尝试这样的事情并且它不接受日期,而只返回familyStats集合中的所有对象。

module.exports.getFamilyStatsPast = function (req, res) {
    var id = req.params.id;
    var days = req.params.days;

    var pastDate = new Date();
    pastDate.setDate(pastDate.getDate() - days).toISOString();
    var currentDate = new Date().toISOString();

    Worksets
        .findById(id)
        .select('familyStats')
        .find({
            createdOn : {
                $gte: pastDate,
                $lte: currentDate
            }
        })
        .exec(function (err, doc){
            var response = {
                status: 200,
                message: []
            };
            if (err){
                console.log("Error finding Workset");
                response.status = 500;
                response.message = err;
            } else if(!doc){
                console.log("Workset id not found in database", id);
                response.status = 404;
                response.message = {"message": "Workset Id not found."}
            }
            if(doc){
                console.log("Found workset: ", doc);
                res
                    .status(response.status)
                    .json(doc)
            } else {
                res
                    .status(response.status)
                    .json(response.message);
            }
        });
};

我基本上想要得到 - 来自Worksets集合的一个名为familyStats的数组 - 然后从那个数组我想要的是pastDatecurrentDate之间创建的对象,这些对象是从上周到现在。

任何想法我做错了什么?

这是我的猫鼬数据模式:

var familyStatsSchema = new mongoose.Schema({
    suspectFamilies: [{
        name: String,
        size: String,
        sizeValue: Number,
        instances: Number,
        elementId: Number
    }],
    totalFamilies: Number,
    unusedFamilies: Number,
    oversizedFamilies: Number,
    inPlaceFamilies: Number,
    createdBy: String,
    createdOn: Date
});

var healthCheckSchema = new mongoose.Schema({
    onOpened: [worksetEventSchema],
    onSynched: [worksetEventSchema],
    itemCount : [worksetItemSchema],
    viewStats: [viewStatsSchema],
    linkStats: [linksStatsSchema],
    familyStats: [familyStatsSchema]
});

mongoose.model('Worksets', healthCheckSchema);

1 个答案:

答案 0 :(得分:2)

如果您只想从文档中的数组中获取特定日期范围内的数据,那么您只需要来自聚合框架的$filter操作:

var id = req.params.id;
var days = parseInt(req.params.days);

var now = new Date(),
    firstDate = new Date(now.valueOf() - ( 1000 * 60 * 60 * 24 * days ));

Worksets.aggregate([
  { "$match": { 
    "_id": ObjectId(id),
    "familyStats": { 
      { "$elemMatch": { "createdOn": { "$gte": firstDate, "$lt": now } } }
  }},
  { "$project": {
    "familtStats": {
      "$filter": {
        "input": "$familyStats",
        "as": "el",
        "cond": { "$and": [
          { "$gte": [ "$$el.createdOn", firstDate ] },
          { "$lt": [ "$$el.createdOn", now ] }
        ]}
      }
    }
  }}
],function(err, results) {
  // work with response
})

有一个初始$match条件与我们指定查询条件的.find()的条件相同。我添加了$elemMatch的日期范围条件,因为如果{"范围表达式&#34}范围内$elemMatch范围内没有日期,则根本没有返回文档的点;实际上是一个应用于数组元素的AND条件。没有它,你只是问整个阵列是否符合这些条件,而不是"如果它们之间存在某种情况"

此处还要注意ObjectId构造函数。猫鼬" autocasts"来自"字符串"的_id字段的值通常情况下,但是使用聚合框架,它无法在其自身上执行此操作。你需要做"演员"手动。因此,从Schema.Types导入并将其应用于此处收到的参数。

在匹配了文档(可能不包括_id约束)后,$project管道阶段确定了"形状"返回的结果。与标准查询投影一样,您必须包含" all"你真正想要的领域。例如,我只是返回有问题的数组。

$filter应用与$match中相同的逻辑条件,除非这次它们实际应用于&#34;数组元素本身&#34; < / em>而不是&#34;文件&#34;符合条件。任何不符合给定条件的内容都将从返回的数组中删除。

这将为您提供与常规.find()查询具有大致相同性能的操作,但使用的运算符能够从数组&#34;之前删除#34之前的不需要的内容&#34; ;结果从服务器返回。

对于像您这样的大型文档,这应该是您对其他阵列执行的常规操作。