Luis
Luis

Reputation: 35

return the last item of an array of objects inside another with mongoose

I am build a chat app which needs to return the last message sended to every user

The document look like this:

{
  username:"username",
  chat:[
  {
    key: "long number",
    messages:[
      {
        sender: "sender",
        content:"a"
      },
      {
        sender: "sender",
        content:"b"
      }
    ]
  },
  {
    key: "long number",
    messages:[
      {
        sender: "sender",
        content:"1"
      },
      {
        sender: "sender",
        content:"2"
      }
    ]
  },
  ]
}

The result I want

[
  {
    key:"long number",
    message:[
      {
        sender:"sender",
        content:"b"
      }
    ]
  },
  {
    key:"long number",
    message:[
      {
        sender:"sender",
        content:"2"
      }
    ]
  }
]

I know how to filter the arrays using javascript array methods but it will be more efficient if i could get the messages using a single mongoose query

Upvotes: 0

Views: 30

Answers (1)

AdamExchange
AdamExchange

Reputation: 1301

https://mongoplayground.net/p/qcBkxntBDbX

db.collection.aggregate([
  // Note you'll probably want a "$match" here to match on the specific document
  // Unwind on chat to access the messages array for each field
  {
    "$unwind": "$chat"
  },
  // Get the last item from the messages array for each chat
  {
    "$addFields": {
      "message": {
        "$arrayElemAt": [
          "$chat.messages",
          -1
        ]
      }
    }
  },
  // Regroup by key
  {
    "$group": {
      "_id": "$chat.key",
      "message": {
        $addToSet: "$message"
      }
    }
  },
  // Rename grouped _id back to "key", remove the _id, and carry forward the message
  {
    "$project": {
      "key": "$_id",
      "message": 1,
      "_id": 0
    }
  }
])

This matches the requirements as you wrote them, but you may want to include the documents _id or something based on your use case. Wouldn't be too tricky to carry that forward in the group stage though.

Upvotes: 1

Related Questions