Mongoose 聚合不按输入日期过滤 [英] Mongoose Aggregation does not Filter by Input Date

查看:13
本文介绍了Mongoose 聚合不按输入日期过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个聚合查询,但是当我将 $match 与日期一起使用时,它并没有像我预期的那样工作.如果我使用其他字段而不是任何 Date 字段,它会按预期工作.我正在使用的代码示例如下:

const res = await Reservation.aggregate([{ $match: { createdAt: { $lte: req.endDate } } }]).exec();const res = await Reservation.find({ createdAt: { $lte: req.endDate } }).exec();

第一行不起作用,但第二行完美无缺..find().aggregate() 有什么区别.感谢您的帮助!

解决方案

Mongoose 有模式",它为你做这种称为自动转换"的神奇事情.设计者在这里想到的典型情况是,所有来自诸如 GETPOST 之类的网络"交互的输入基本上都包含在一个字符串"中.

无论是否有一些帮助程序可以将参数转换为具有键和值的对象,所有这些值"仍然是字符串",或者可能在适当的情况下由相同的帮助程序"直接变为数字.这是常见的网页框架设计.

因此,当您发出 .find() 时,此函数完全无法更改返回的内容,除了省略字段/属性之外,因此模式"已应用.

.aggregate() 方法完全不同.它的全部存在是修改包含在文档和集合中的内容.这样做的结果是不可能"应用模式.

因此,.find() 等方法中出现的自动转换"不会发生,并且您需要转换元素(例如字符串"日期"作为 ) 发送到自己的正确类型:

Reservation.aggregate([{ "$match": { "createdAt": { "$lte": new Date(req.endDate) } } }])

即使您所做的只是一个 $match 并且您没有以任何方式修改"架构,猫鼬也不会假定"这一点并且不会尝试转换为匹配模式中的字段.

这里的逻辑是 $match 阶段或任何类似的可以绑定到类型"的东西,可以发生在管道内的任何地方.因此,无法保证流水线阶段处理的文档与原始集合模式有任何相似之处.

可以说它可以"考虑这样一个事实,即这是第一个管道阶段,在那里什么都不会改变,并进行类似的检查.但这不是当前代码库的工作方式.

所以简而言之,在使用聚合管道时,所有需要专门转换为类型(Date、ObjectId 等)的对象都需要在您的代码中手动"转换,而不是假设 mongoose 会这样做以其他方式为您服务.

I'm trying to build a aggregation query but when I use $match with dates, it doesn't work as I expect. If I use other fields instead of any Date field, it works as expected. The code examples I'm using is below:

const res = await Reservation.aggregate([{ $match: { createdAt: { $lte: req.endDate } } }]).exec();

const res = await Reservation.find({ createdAt: { $lte: req.endDate } }).exec();

The first line doesn't work but the second one works perfectly. What is the difference between .find() and .aggregate(). Thanks for your help!

解决方案

Mongoose has "schemas" for which it does this magic thing called "autocasting" for you. The typical case the designer(s) have in mind here is that all input from "web" interations like GET and POST is basically contained in a "string".

Whether or not there is some helper that that makes paramters into objects with keys and values, all those "values" are still "strings", or possibly made directly numeric by the same "helpers" where appropriate. This is common web framework design.

So when you issue a .find(), this function is completely incapable of altering the returned content other than by omission for fields/properties, so hence the "schema" is applied.

The .aggregate() method is entirely different. It's entire existence is to modify content contained in documents and collections. The consequence of this is that it is "impossible" for a schema to apply.

Hence, the "autocasting" present in methods like .find() does not happen, and you are required to cast elements ( such as the "string" your "date" is being sent in as ) to the correct types yourself:

Reservation.aggregate([
   { "$match": { "createdAt": { "$lte": new Date(req.endDate) } } }
])

Even if all you are doing is a $match and that you have not "modified" the schema in any way, mongoose does not "presume" this and does not attempt to cast to the matching field in the schema.

The logic here is that a $match stage or anything similar that could be bound to a "type", could occur anywhere within the pipeline. As such there is no guarantee that the documents being acted on by a pipeline stage bear any resemblance to the original collection schema.

Arguably it "could" possibly consider the fact that this is the first pipeline stage where nothing could possibly have changed and do a similar inspection. But that is not how the current code base worked.

So in short, when using the aggregation pipeline, all objects that need to be specifically cast to a type ( Date, ObjectId, etc ) need to be "manually" cast in your code, rather than assuming mongoose is going to do it for you like in other methods.

这篇关于Mongoose 聚合不按输入日期过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆