查询按计算日期查找

时间:2015-09-06 21:33:38

标签: node.js mongodb mongoose mongodb-query

我想在mongoose中创建一个查询来实现此功能:

Mongoose模特:

Planted_crop: owner: id, date_planted: Date, crop: id, quantity: Number
Crop: name: String, water_consumption: Number, grow_time: Number (means hours)

现在我想得到所有尚未完全种植的种植作物,在半代码中就是这样:

if (plantedCrop.date_planted < plantedCrop.date_planted + plantedCrop.crop.grow_time) {
    // this crop should be selected
}

现在我需要将其转换为mongodb:

var PlantedCrop = mongoose.model("planted_crop");
PlantedCrop.find({ 
    date_planted: { 
        $lt: {
            date_planted + crop.grow_time * 3600
        }
    }
}).populate("crop").exec(function(err, crops) {
    // calculate water consumption
    var consumption = 0, planted;
    for (var i = 0; i < crops.length; i++) {
        planted = crops[i];
        consumption += planted.crop.water_consumption * planted.quantity;
    }
    console.log("Water consumption of planted crops is " + consumption + " liters.
});

我坚持创建此类查询,有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

你不应该这样做,因此答案的最佳部分将解释为什么你不想要这种方法。相反,你应该计算在创建时grop将会增长的时间,这实际上只是维护一个额外的字段(只显示必需的字段):

var date = new Date();

PlantedCrop.create({
    "owner": ownerId,
    "crop": cropId,
    "date"_planted": date,
    "grow_time": ( 1000 * 60 * 60 ) * 2, // "milliseconds" for two hours
    "ready_time": new Date( date.valueOf() + ( 1000 * 60 * 60 ) * 2)
});

然后找出当前没有完全种植的作物&#34;从目前的时间开始很简单:

PlantedCrop.find({ "ready_time": { "$gte": new Date() } },function(err,crops) {

});

如果你想要的东西已经准备好&#34;从当前日期起一个小时,你就可以了:

PlantedCrop.find({ 
   "ready_time": { 
       "$gte": new Date( Date.now + ( 1000 * 60 * 60 ) )
   } 
},function(err,crops) {

});

这在功能上很简单,并且没有混淆,因为所有信息都是在写入时记录下来的,你只需要查看它是否已经成长。

&#34;危险&#34;在计算方面考虑到这一点,你开始使用$where类型的查询和JavaScript评估字段:

PlantedCrop.find({
    "$where": function() {
        return this.date_planted.valueOf() + grow_time > Date.now;
    }
},function(err,crops) {

}); 

这是非常糟糕,因为这样的测试不能使用索引进行搜索,而且会非常强大的&#34;尝试匹配集合中的每个文档。

这是您想要避免的以及您希望在处理逻辑中保持清洁的内容,但另一种选择是在创建请求时在客户端上进行数学运算。只需向后工作,检查作物是否种植了不到一小时&#34;之前,成长时间实际上更大:

PlantedCrop.find({ 
   "date_planed": { 
       "$lte": new Date( Date.now - ( 1000 * 60 * 60 ) )
   },
   "grow_time": { "$gte": ( 1000 * 60 * 60 ) }
},function(err,crops) {

});

那会找到你所有的庄稼和#34;没有完全成长&#34;在你问的时间范围内。

但至于最初的观点,它看起来很笨拙,只是通过存储最终的计算日期并仅仅查询它来解决。

另外,请确保所有这些数据都在一个集合中,正如开头所建议的那样。您不能在这样的查询中引用填充项目中的值,因为它被称为&#34; join&#34 ;, MongoDB不会这样做。人口仅仅是&#34; prettfies&#34;对象引用通过执行另一个查询来将这些对象引用替换为整个对象,&#34;&#34;初始查询已完成。