Home > Back-end >  I need to sort my data based on date at user level
I need to sort my data based on date at user level

Time:10-14

I have this data which is in multiple email format, I have many test users for which I want to match with one and get that user's Date to sort my data. The data is:

[
 {
    _id: "60642127b982sa55299q674444a",
    subject: "Email 1",
    body: "Body 1",
    to: [
    {
      email_id: "[email protected]",
      name: "test 1",
      date: "2021-10-01 12:00:00"
    },
    {
      email_id: "[email protected]",
      name: "test 2",
      date: "2021-10-01 13:00:00"
    }
    ],
   cc: [
     {
       email_id: "[email protected]",
       name: "test 3",
       date: "2021-10-01 14:00:00"
     },
     {
       email_id: "[email protected]",
       name: "test 4",
       date: "2021-10-01 15:00:00"
     }
   ],
   bcc: [
     {
       email_id: "[email protected]",
       name: "test 5",
       date: "2021-10-01 16:00:00"
     },
     {
       email_id: "[email protected]",
       name: "test 6",
       date: "2021-10-01 17:00:00"
     },
     {
       email_id: "[email protected]",
       name: "test 2",
       date: "2021-10-01 13:00:00"
     }
    ]
   },
   {
    _id: "60642127b982sa55299q674444b",
   subject: "Email 2",
   body: "Body 2",
   to: [
     {
       email_id: "[email protected]",
       name: "test 1",
       date: "2021-10-01 12:10:00"
     },
     {
       email_id: "[email protected]",
       name: "test 2",
       date: "2021-10-01 13:10:00"
     }
   ],
   cc: null,
   bcc: [
     {
       email_id: "[email protected]",
       name: "test 5",
       date: "2021-10-01 16:10:00"
     },
     {
       email_id: "[email protected]",
       name: "test 6",
       date: "2021-10-01 17:10:00"
     }
   ]
   },
   {
   _id: "60642127b982sa55299q674444c",
   subject: "Email 3",
   body: "Body 2",
   to: [
     {
       email_id: "[email protected]",
       name: "test 1",
       date: "2021-10-01 12:10:00"
     },
     {
       email_id: "[email protected]",
       name: "test 2",
       date: "2021-10-01 13:15:00"
     }
   ],
   cc: null,
   bcc: null
   },
   {
   _id: "60642127b982sa55299q674444d",
   subject: "Email 4",
   body: "Body 2",
   to: [
     {
       email_id: "[email protected]",
       name: "test 1",
       date: "2021-10-01 12:10:00"
     },
     {
       email_id: "[email protected]",
       name: "test 3",
       date: "2021-10-01 13:10:00"
     }
   ],
   cc: null,
   bcc: [
     {
       email_id: "[email protected]",
       name: "test 2",
       date: "2021-10-01 12:10:00"
     },
     {
       email_id: "[email protected]",
       name: "test 6",
       date: "2021-10-01 17:10:00"
     }
   ]
   },
   {
   _id: "60642127b982sa55299q674444e",
   subject: "Email 5",
   body: "Body 2",
   to: [
     {
       email_id: "[email protected]",
       name: "test 1",
       date: "2021-10-01 12:15:00"
     },
     {
       email_id: "[email protected]",
       name: "test 3",
       date: "2021-10-01 14:10:00"
     }
   ],
   cc: [
     {
       email_id: "[email protected]",
       name: "test 2",
       date: "2021-10-01 16:50:00"
     },
     {
       email_id: "[email protected]",
       name: "test 5",
       date: "2021-10-01 16:10:00"
     }
   ],
   bcc: null
 }
]

I am looking for a mongodb query to fetch my userID ([email protected]) and sort it based on [email protected]'s date. I want my result to be sorted based on date in ascending order as Email 4, Email 1, Email 2, Email 3,Email 5.

[
 {
   "_id": null,
   "uniqueValues": {
     "_id": "60642127b982sa55299q674444d",
     "body": "Body 4",
     "concat": {
       "date": "2021-10-01 12:10:00",
       "email_id": "[email protected]",
       "name": "test 2"
     },
     "subject": "Email 4"
   }
 },
 {
   "_id": null,
   "uniqueValues": {
     "_id": "60642127b982sa55299q674444a",
     "body": "Body 1",
     "concat": {
       "date": "2021-10-01 13:00:00",
       "email_id": "[email protected]",
       "name": "test 2"
     },
     "subject": "Email 1"
   }
 },
 {
   "_id": null,
   "uniqueValues": {
     "_id": "60642127b982sa55299q674444b",
     "body": "Body 2",
     "concat": {
       "date": "2021-10-01 13:10:00",
       "email_id": "[email protected]",
       "name": "test 2"
     },
     "subject": "Email 2"
   }
 },
 {
   "_id": null,
   "uniqueValues": {
     "_id": "60642127b982sa55299q674444c",
     "body": "Body 3",
     "concat": {
       "date": "2021-10-01 13:15:00",
       "email_id": "[email protected]",
       "name": "test 2"
     },
     "subject": "Email 3"
   }
 },
 {
   "_id": null,
   "uniqueValues": {
     "_id": "60642127b982sa55299q674444e",
     "body": "Body 5",
     "concat": {
       "date": "2021-10-01 16:50:00",
       "email_id": "[email protected]",
       "name": "test 2"
     },
     "subject": "Email 5"
   }
 }
 ]

I have used this query,I'm not getting the proper results. some of the documents are skipped. If anyone has any idea, please respond.

db.collection.aggregate([
{
"$match": {
  "$or": [
    {
      "to.email_id": "[email protected]"
    },
    {
      "cc.email_id": "[email protected]"
    },
    {
      "bcc.email_id": "[email protected]"
    }
  ]
 }
 },
 {
"$project": {
  subject: 1,
  body: 1,
  concat: {
    $concatArrays: [
      "$to",
      "$cc",
      "$bcc"
    ]
  }
  }
 },
 {
"$unwind": "$concat"
 },
 {
"$match": {
  "concat.email_id": "[email protected]"
  }
 },
])

CodePudding user response:

The $concatArrays operator requires all of its inputs to be arrays.

From the docs:

If any argument resolves to a value of null or refers to a field that is missing, $concatArrays returns null.

For those documents where the cc field is null, the result of $concatArrays assigned to the concat field will be null.

This means that the field concat.email_id will not exist, and therefore will not match.

You might use the $ifNull operator to replace any null values with an empty array, like

{$ifNull: [ "$cc", [] ]}

CodePudding user response:

Hope , you have expected the following aggregation. I have added / modified few stages with your pipeline.

  • $match to eliminate unwated documents
  • $ifNull helps what we need to do when variables is null, So I passed [] empty array if variable is null
  • $concatArrays to concat all 3 arrays
  • $unwind to deconstruct the array
  • $group to reconstruct the array, but without any duplications. Because I added 3 conditions to remove duplicate inside _id
  • $sort to sort the documents

Here is the code

db.collection.aggregate([
  {
    "$match": {
      "$or": [
        { "to.email_id": "[email protected]" },
        { "cc.email_id": "[email protected]" },
        { "bcc.email_id": "[email protected]" }
      ]
    }
  },
  {
    "$project": {
      subject: 1,
      body: 1,
      concat: {
        $concatArrays: [
          { $ifNull: [ "$to", [] ] },
          { $ifNull: [ "$cc", [] ] },
          { $ifNull: [ "$bcc", [] ] }
        ]
      }
    }
  },
  { "$unwind": "$concat" },
  { "$match": { "concat.email_id": "[email protected]" } },
  {
    "$group": {
      "_id": { _id: "$_id", date: "$concat.date", email: "$concat.email_id" },
      "body": { "$first": "$body" },
      "concat": { "$first": "$concat" },
      "subject": { "$first": "$subject" }
    }
  },
  { "$sort": { "concat.date": 1 } },
  { $addFields: { _id: "$_id._id" } }
])

Working Mongo playground

  • Related