简体   繁体   English

如何在MongoDB中获取最近n个月的记录(只考虑每月的最后一个条目)

[英]How to fetch the last n months record(consider only the last entry per month) in MongoDB

I am new to MongoDb.我是 MongoDb 的新手。 I need help to fetch the last n month record, there might be multiple entry per month but the query needs to return only the last entry per month.我需要帮助来获取最后 n 个月的记录,每个月可能有多个条目,但查询只需要返回每个月的最后一个条目。

For eg lets say if n is 3 and userId is userId1 (that means return last 3 month record for userId1 ).对于如让说,如果n是3和用户id userId1 (这意味着返回过去的3月历史的userId1 )。

Sample inputs in the collection:集合中的示例输入:

[
 {
   "_id": objectId("aaaaaa"),
   "userId": "userId1",
   "processedAt": "2021-06-01T12:16:49.349Z"
 },
 {
   "_id": objectId("bbbbb"),
   "userId": "userId1",
   "processedAt": "2021-10-11T12:16:49.349Z"
 },
 {
   "_id": objectId("ccccc"),
   "userId": "userId1",
   "processedAt": "2021-10-25T12:16:49.349Z"
 },
 {
   "_id": objectId("eeeee"),
   "userId": "userId1",
   "processedAt": "2021-09-12T12:16:49.349Z"
 },
 {
   "_id": objectId("fffff"),
   "userId": "userId1",
   "processedAt": "2021-09-28T12:16:49.349Z"
 },
 {
   "_id": objectId("ggggg"),
   "userId": "userId1",
   "processedAt": "2021-09-23T12:16:49.349Z"
 },
 {
   "_id": objectId("hhhhh"),
   "userId": "userId1",
   "processedAt": "2021-07-23T12:16:49.349Z"
 },
 {
   "_id": objectId("iiiii"),
   "userId": "userId2",
   "processedAt": "2021-09-29T12:16:49.349Z"
 },
 {
   "_id": objectId("jjjjj"),
   "userId": "userId1",
   "processedAt": "2022-01-29T12:16:49.349Z"
 },
 {
   "_id": objectId("kkkkk"),
   "userId": "userId1",
   "processedAt": "2022-02-29T12:16:49.349Z"
 }, 
]

Expected Result: Should return by userId, limit n months(fetch only the last saved entry of the month) and the ascending order of the month of processedAt:预期结果:应按userId返回,限制n个月(只获取当月最后保存的条目)和processedAt月份的升序:

[{
    "_id": objectId("ccccc"),
    "userId": "userId1",
    "processedAt": "2021-10-25T12:16:49.349Z"
},
{
    "_id": objectId("jjjjj"),
    "userId": "userId1",
    "processedAt": "2022-01-29T12:16:49.349Z"
  },
  {
    "_id": objectId("kkkkk"),
    "userId": "userId1",
    "processedAt": "2022-02-29T12:16:49.349Z"
  }
]

I have tried below query however which is returning all the records.我尝试过下面的查询,但是它返回了所有记录。 I want query needs to consider only the last entry per month.我希望查询只需要考虑每月的最后一个条目。 I have been using mongojs driver v4.1.2我一直在用mongojs驱动v4.1.2

db.collection(collection_name)
                .find({ userId: userId }, { projection: { _id: 0 } })
                .sort({ processedAt: -1 })
                .limit(n)
                .toArray()

Starting from MongoDB 5.0 ,从 MongoDB 5.0 开始

You can use $setWindowFields to aggregate a "rank" for the "partition" / "group" (ie the month in your example) and only choose the document with top rank.您可以使用$setWindowFields为“分区”/“组”(即您示例中的月份)聚合“排名”,并仅选择排名最高的文档。

The ranking can be defined as processedAt: -1 as you want to keep only the latest record in the month with highest rank.排名可以定义为processedAt: -1因为您只想保留最高排名月份的最新记录。

{
    "$setWindowFields": {
      "partitionBy": {
        "$dateToString": {
          "date": "$processedAt",
          "format": "%Y-%m"
        }
      },
      "sortBy": {
        "processedAt": -1
      },
      "output": {
        "rank": {
          $rank: {}
        }
      }
    }
  }

Here is the Mongo playground for your reference.这是Mongo 游乐场供您参考。

For MongoDB 3.6+,对于 MongoDB 3.6+,

As the sample dataset is using ISODate format, it is possible to sort and group the field by leftmost 7 characters (ie yyyy-MM).由于样本数据集使用 ISODate 格式,因此可以按最左边的 7 个字符(即 yyyy-MM)对字段进行排序和分组。 Keeping only the first document inside the month group should do the tricks.只保留月组中的第一个文档应该可以解决问题。

{
    $sort: {
      processedAt: -1
    }
  },
  {
    "$addFields": {
      "month": {
        "$substrCP": [
          "$processedAt",
          0,
          7
        ]
      }
    }
  },
  {
    $group: {
      _id: "$month",
      last: {
        $first: "$$ROOT"
      }
    }
  }

Here is the Mongo playground .这里是Mongo 游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM