MongoDB 聚合查询以过滤 7 天前创建的文档

MongoDB aggregate query to filter documents created 7 days ago

我想过滤数据集以提取 7 天前创建的文档 OR 一个月前 OR 在任何日期创建的文档.

根据文档中的 createdAt 字段过滤文档。

数据集:-

[
  {
    "_id": ObjectId("6257047cffd61ab62864c1ae"),
    "type": "A",
    "source": "B",
    "user": ObjectId("622b55ff0b0af6b049c387d3"),
    "createdAt": ISODate("2022-04-17T07:55:00.368Z"),
    "updatedAt": ISODate("2022-04-17T07:55:00.368Z"),
    
  },
  {
    "_id": ObjectId("6257047cffd61ab62864c1ad"),
    "type": "B",
    "source": "A",
    "user": ObjectId("622b55ff0b0af6b049c387d3"),
    "createdAt": ISODate("2022-04-23T07:55:00.368Z"),
    "updatedAt": ISODate("2022-04-23T07:55:00.368Z"),
    
  },
  {
    "_id": ObjectId("6257047cffd61ab62864c1ce"),
    "type": "A",
    "source": "C",
    "user": ObjectId("622b55ff0b0af6b049c387d3"),
    "createdAt": ISODate("2022-04-17T07:55:00.368Z"),
    "updatedAt": ISODate("2022-04-17T07:55:00.368Z"),
    
  },
  {
    "_id": ObjectId("6257047cffd61ab62864c1cb"),
    "type": "A",
    "source": "B",
    "user": ObjectId("622b56250b0af6b049c387d6"),
    "createdAt": ISODate("2022-04-24T07:55:00.368Z"),
    "updatedAt": ISODate("2022-04-24T07:55:00.368Z"),
    
  },
  {
    "_id": ObjectId("6257047cffd61ab62864c1cb"),
    "type": "A",
    "source": "B",
    "user": ObjectId("622b56250b0af6b049c387d6"),
    "createdAt": ISODate("2022-03-24T07:55:00.368Z"),
    "updatedAt": ISODate("2022-03-24T07:55:00.368Z"),
    
  },
  {
    "_id": ObjectId("6257047cffd61ab62864c1ce"),
    "type": "A",
    "source": "C",
    "user": ObjectId("622b55ff0b0af6b049c387d3"),
    "createdAt": ISODate("2022-03-17T07:55:00.368Z"),
    "updatedAt": ISODate("2022-03-17T07:55:00.368Z"),
    
  },
  
]

MongoDB聚合查询:-

db.collection.aggregate([
  {
    $addFields: {
      paramType: "All",
      paramSource: "All",
      paramCreatedAt:"All",
    }
  },
  {
    $match: {
      $and: [
        {
          user: ObjectId("622b55ff0b0af6b049c387d3")
        },
        {
          $or: [
            {
              paramType: {
                $eq: "All"
              }
            },
            {
              $expr: {
                $eq: [
                  "$paramType",
                  "$type"
                ],
                
              }
            }
          ]
        },
        {
          $or: [
            {
              paramSource: {
                $eq: "All"
              }
            },
            {
              $expr: {
                $eq: [
                  "$paramSource",
                  "$source"
                ]
              }
            }
          ]
        }
      ]
    }
  },
  {
    $setWindowFields: {
      output: {
        totalCount: {
          $count: {}
        }
      }
    }
  },
  {
    $sort: {
      createdAt: -1
    }
  },
  {
    $skip: 0
  },
  {
    $limit: 6
  },
  {
    "$project": {
      "paramSource": false,
      "paramType": false,
      
    }
  }
])

如何过滤以获取最近 7 天或 30 天或任何日期内创建的文档。

paramCreatedAt 将采用以下值之一 [All dates, 7 days ago, a month ago]

例子:-

你的骨架很整齐,其实很接近。对于日期过滤,只需使用 $dateDiff 到 return 日期差异(以天为单位),然后使用 $switch[=14 将其与您选择的天数间隔(即 7 天或 30 天)进行比较=]

db.collection.aggregate([
  {
    $addFields: {
      paramType: "All",
      paramSource: "All",
      paramCreatedAt: "All dates"// [All dates, 7 days ago, a month ago]
      
    }
  },
  {
    $match: {
      $and: [
        {
          user: ObjectId("622b55ff0b0af6b049c387d3")
        },
        {
          $or: [
            {
              paramType: {
                $eq: "All"
              }
            },
            {
              $expr: {
                $eq: [
                  "$paramType",
                  "$type"
                ],
                
              }
            }
          ]
        },
        {
          $or: [
            {
              paramSource: {
                $eq: "All"
              }
            },
            {
              $expr: {
                $eq: [
                  "$paramSource",
                  "$source"
                ]
              }
            }
          ]
        },
        {
          $or: [
            {
              paramCreatedAt: {
                $eq: "All dates"
              }
            },
            {
              $expr: {
                $and: [
                  {
                    "$in": [
                      "$paramCreatedAt",
                      [
                        "7 days ago",
                        "a month ago"
                      ]
                    ]
                  },
                  {
                    $lte: [
                      {
                        "$dateDiff": {
                          "startDate": "$createdAt",
                          "endDate": "$$NOW",
                          "unit": "day"
                        }
                      },
                      {
                        "$switch": {
                          "branches": [
                            {
                              "case": {
                                $eq: [
                                  "$paramCreatedAt",
                                  "7 days ago"
                                ]
                              },
                              "then": 7
                            },
                            {
                              "case": {
                                $eq: [
                                  "$paramCreatedAt",
                                  "a month ago"
                                ]
                              },
                              "then": 30
                            }
                          ]
                        }
                      }
                    ]
                  }
                ]
              }
            }
          ]
        }
      ]
    }
  },
  {
    $setWindowFields: {
      output: {
        totalCount: {
          $count: {}
        }
      }
    }
  },
  {
    $sort: {
      createdAt: -1
    }
  },
  {
    $skip: 0
  },
  {
    $limit: 6
  },
  {
    "$project": {
      "paramSource": false,
      "paramType": false,
      
    }
  }
])

这里是Mongo playground供大家参考。

这是使用 $facet 的替代方法。 $facet 非常方便,因为它允许您“并行匹配和分组”并创建 重叠 文档桶。在聚合字段上具有 $group$cond 的单个管道适用于不需要重叠且需要优先顺序的“if/then/elif/elif/else”结构。

db.foo.aggregate([
    // Initial filter(s):                                                                                                    
    {$match: {user: ObjectId("622b55ff0b0af6b049c387d3")}},

    // Create a single version of "now" from the perspective of the                                                          
    // CLIENT to use in queries to follow.                                                                                   
    // To create such a target date from the perspective of the SERVER,                                                      
    // use  {$addFields: {DD: '$$NOW'}}                                                                                      
    // Probably overkill but OK.                                                                                             
    {$addFields: {DD: new ISODate()}},

    {$facet: {
        "all": [ ],   // not exciting!  :-)                                                                                  

        "exactly_7_days_ago": [
            {$match: {$expr:
                      {$eq: [7, {$floor: {$divide:[{$subtract:['$DD', '$createdAt'] }, 1000 * 60 * 60 * 24]}} ]}
                     }}
        ],
        "everything_from_last_month": [
            {$match: {$expr:
                      {$eq: [1, {$subtract:[{$month: '$DD'}, {$month: '$createdAt'} ]} ]}
                     }}
        ],
        "only_one_day_from_last_month": [
            {$match: {$expr:
                      {$and: [
                          {$eq: [1, {$subtract:[{$month: '$DD'}, {$month: '$createdAt'}]} ]},
                          {$eq: [0, {$subtract:[{$dayOfMonth: '$DD'}, {$dayOfMonth: '$createdAt'} ]} ]}
                      ]}
                     }}
        ],
    }}

]);