简体   繁体   中英

How to access nested array of objects in mongodb aggregation pipeline?

I have a document like this(this is the result after few pipeline stages)

[
  {
    "_id": ObjectId("5e9d5785e4c8343bb2b455cc"),
    "name": "Jenny Adams",
    "report": [
      { "category":"Beauty", "status":"submitted", "submitted_on": [{"_id": "xyz", "timestamp":"2022-02-23T06:10:05.832+00:00"}, {"_id": "abc", "timestamp":"2021-03-23T06:10:05.832+00:00"}] },
      { "category":"Kitchen", "status":"submitted", "submitted_on": [{"_id": "mnp", "timestamp":"2022-05-08T06:10:06.432+00:00"}] }
    ]
  },
  {
    "_id": ObjectId("5e9d5785e4c8343bb2b455db"),
    "name": "Mathew Smith",
    "report": [
      { "category":"Household", "status":"submitted", "submitted_on": [{"_id": "123", "timestamp":"2022-02-23T06:10:05.832+00:00"}, {"_id": "345", "timestamp":"2021-03-23T06:10:05.832+00:00"}] },
      { "category":"Garden", "status":"submitted", "submitted_on": [{"_id": "567", "timestamp":"2022-05-08T06:10:06.432+00:00"}] },
      { "category":"BakingNeeds", "status":"submitted", "submitted_on": [{"_id": "891", "timestamp":"2022-05-08T06:10:06.432+00:00"}] }
    ]
  }
]

I have user input for time period -

from - 2021-02-23T06:10:05.832+00:00
to - 2022-02-23T06:10:05.832+00:00

Now I wanted to filter the objects from the report which lie in a certain range of time, I want to only keep the object if the "submitted_on[-1]["timestamp"]" is in range of from and to date timestamp. I am struggling with accessing the timestamp because of the nesting I tried this

$project: {
  "name": 1,
  "report": {
    "category": 1,
    "status": 1,
    "submitted_on": 1,
    "timestamp": {
      $arrayElemAt: ["$report.cataloger_submitted_on", -1]
    }
  }
}

But this gets the last object of the report array {"_id": "bcd", "timestamp":"2022-05-08T06:10:06.432+00:00"} for all the items inside the report. How can I do this to select the last timestamp of each obj.

You can replace your phase in the aggregation pipeline with two phases: $unwind and $addFields in order to get what I think you want:

  {
    $unwind: "$report"
  },
  {
    "$addFields": {
      "timestamp": {
        $arrayElemAt: [
          "$report.submitted_on",
          -1
        ]
      }
    }
  },

The $unwind phase is breaking the external array into documents since you want to perform an action on each one of them. See the playground here with your example. If you plan to continue the aggregation pipeline with more steps, you can probably skip the $addFields phase and include the condition inside your next $match phase.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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