动态MongoDB聚合使用$$NOW

huangapple go评论52阅读模式
英文:

Dynamic MongoDB aggregation using $$NOW

问题

同行们;

是否有人能够友善地解释一下这个问题,这个问题已经困扰我几天了?这应该是一件简单的事情,但我似乎找不到问题出在哪里...

我需要从一个集合中检索一年的记录,根据今天的日期。简而言之,如果今天是2023-02-15,我需要检索2022-02-15之后创建的记录。

这当然可以工作:

[
  { 
    $match: { _created: { $gte: ISODate("2022-02-15") } }
  }
]

问题在于,当尝试创建一个不需要不断更新的聚合时,$$NOW 似乎不起作用,我无法理解为什么。

例如,这个不起作用:

[
  {
    $match:
    {
       _created:
       {
         $gte:
         { 
           $subtract: [ "$$NOW", { $multiply: [1000, 60, 60, 24, 365] } ]
         }
       }
    }
  }
]

这个也不起作用:

[
  {
    $set: 
    { 
      startDate: { $subtract: [ "$$NOW", { $multiply: [1000, 60, 60, 24, 365] } ] }
    }
  },
  {
    $match:
    {
      _created: { $gte: ISODate("$startDate") }
    }
  }
]

我尝试过移动元素,解析 $$NOW 的结果以获取只有日期部分,将其转换为不同的类型... 结果总是一样的:没有错误,但也没有筛选记录。

我有一种感觉,答案可能是我正在忽略的一些非常愚蠢的东西。

有更有经验的人能伸出援手吗?

附言:在检索所需的记录后,聚合会继续,我只是没有列出发生的事情,因为问题只涉及记录的匹配。我们的 Mongod 版本是 6.0.3,我正在使用 MongoDB Compass,想法是将这个聚合保存为一个查询,以响应 API 调用提供答案。

英文:

Fellows;

Would anyone be so kind as to shed a light on this matter which has been stumping me for a few days now? It should be something simple, but I can't seem to find where the problem lies...

I need to retrieve one year worth of records from a collection based on today's date. Simply put, if today is 2023-02-15, I need records created after 2022-02-15.

This works, of course:

[
  { 
    $match: { _created: { $gte: ISODate("2022-02-15") } }
  }
]

The problem is that, when trying to create an aggregation that does not need to constantly be updated, $$NOW does not seem to work and I cannot understand why.

For example, this does not work:

[
  {
    $match:
    {
       _created:
       {
         $gte:
         { 
           $subtract: [ "$$NOW", { $multiply: [1000, 60, 60, 24, 365] } ]
         }
       }
    }
  }
]

And this doesn't either:

[
  {
    $set: 
    { 
      startDate: { $subtract: [ "$$NOW", { $multiply: [1000, 60, 60, 24, 365] } ] }
    }
  },
  {
    $match:
    {
      _created: { $gte: ISODate("$startDate") }
    }
  }
]

I have tried moving things around, parsing the result of $$NOW to get just the date part, converting it to different types... The result is always the same: No errors, but no filtered records either.

And I have the feeling the answer might be something really silly I am just overlooking.

Can someone more experienced lend a helping hand?

P.S.: The aggregation continues after the required records are retrieved, I just did not care to list what happens because the problem relates only to the matching of records. Our Mongod version is 6.0.3, I am working on MongoDB Compass and the idea is to save this aggregation as a query which provides answers to an API call.

答案1

得分: 2

你需要使用$expr$gte聚合运算符(不要与$gte查询运算符混淆)。在MongoDB 5.0及更新版本中,你还可以使用日期表达式运算符,比如$dateSubtract

{
  $match:
  {
    $expr:
    {
      $gte:
        [ "$_created", { $dateSubtract: { startDate: "$$NOW", unit: "year", amount: 1 } } ]
    }
  }
}
英文:

You need to use $expr and $gte aggregation operator (do not mistake with $gte Query Operator). In MongoDB 5.0 and newer, you can also use Date Expression Operators like $dateSubtract

  {
    $match:
    {
       $expr:
       {
         $gte:
           [ "$_created", { $dateSubtract: { startDate: "$$NOW", unit: "year", amount: 1 } } ]
       }
    }
  }

huangapple
  • 本文由 发表于 2023年2月16日 05:51:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75465762.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定