Search code examples
pythonmongodbaggregation-framework

How to combine filer and sortArray on stage project in mongodb


hi guys i need some help, i want to make some projection on specific field, but inside the projection stage i want also make a filter based on some condition and make a sorting. this is aggregation

[
{
    '$match': {
        '_id': ObjectId('659dfebd24358fa4604510bb')
    }
}, {
    '$project': {
        'date': 1, 
        'serviceScheduleId': 1, 
        'serviceId': 1, 
        'branchOfficeId': 1, 
        'companyId': 1, 
        'queue': {
            '$filter': {
                'input': '$queue', 
                'cond': {
                    '$and': [
                        {
                            '$eq': [
                                '$$this.queueType', 'online'
                            ]
                        }, {
                            '$eq': [
                                '$$this.checkinTime', None
                            ]
                        }, {
                            '$eq': [
                                '$$this.user.status', 'incall'
                            ]
                        }
                    ]
                }
            }, 
            '$sortArray': {
                'input': '$queue', 
                'sortBy': {
                    'user.ticketInt': -1
                }
            }
        }
    }
}, {
    '$group': {
        '_id': '$_id', 
        'items': {
            '$push': '$queue'
        }
    }
}, {
    '$unwind': {
        'path': '$queue'
    }
}

]

and this is my mongodb playground https://mongoplayground.net/p/WNnSOzQKUJB

when i excecute thet code on mongodb compas it show some error like this

Invalid $project :: caused by :: FieldPath field names may not start with '$'. Consider using $getField or $setField.


Solution

  • You can't use the field with the prefix: $ as the field name.

    Approach 1: Create another $set / $project stage

    db.collection.aggregate([
      // Match stage,
      {
        "$project": {
          "date": 1,
          "serviceScheduleId": 1,
          "serviceId": 1,
          "branchOfficeId": 1,
          "companyId": 1,
          "queue": {
            "$filter": {
              "input": "$queue",
              "cond": {
                "$and": [
                  {
                    "$eq": [
                      "$$this.queueType",
                      "online"
                    ]
                  },
                  {
                    "$eq": [
                      "$$this.checkinTime",
                      null
                    ]
                  },
                  {
                    "$eq": [
                      "$$this.user.status",
                      "incall"
                    ]
                  }
                ]
              }
            }
          }
        }
      },
      {
        $set: {
          queue: {
            "$sortArray": {
              "input": "$queue",
              "sortBy": {
                "user.ticketInt": -1
              }
            }
          }
        }
      }
    ])
    

    Demo (Approach 1) @ Mongo Playground

    Approach 2: Place the $filter operator in input field of $sortArray

    db.collection.aggregate([
      // Match stage,
      {
        "$project": {
          "date": 1,
          "serviceScheduleId": 1,
          "serviceId": 1,
          "branchOfficeId": 1,
          "companyId": 1,
          "queue": {
            "$sortArray": {
              "input": {
                "$filter": {
                  "input": "$queue",
                  "cond": {
                    "$and": [
                      {
                        "$eq": [
                          "$$this.queueType",
                          "online"
                        ]
                      },
                      {
                        "$eq": [
                          "$$this.checkinTime",
                          null
                        ]
                      },
                      {
                        "$eq": [
                          "$$this.user.status",
                          "incall"
                        ]
                      }
                    ]
                  }
                }
              },
              "sortBy": {
                "user.ticketInt": -1
              }
            }
          }
        }
      }
    ])
    

    Demo (Approach 2) @ Mongo Playground