Custom error messages from queries based on data in the collection in mongodb

Hello,

I’m wondering if there’s a way to return custom errors and/or messages from queries depending on the data in the dataset.

For example and clarification, consider that I have the following collection, named users, with data in this format:

{
     "_id": "65506e0b9ab7d8f1f9e23373",
     "first_name": "John",
     "last_name": "Smith",
     "age": 33,
     "occupation": "Software engineer",
     "is_active": false,
}

And I would like to change the occupation field if the _id field matches AND the is_active field is true, however, I would also like to know the reason why the document wasn’t updated if it wasn’t.

One way to do this of course is by fetching the document that matches the _id field then validate (using programming language code) if the field is_active == true and if it is, then use an update query to update the occupation field, but it seems wasteful to me to make two queries for a simple update.

The logic I’m looking for in a SINGLE query is something similar to:

if there is a document with _id that matches then:
    if document.is_active == false:
        return CUSTOM_INACTIVE_USER_ERROR
    else:
        update document.occupation to the new value

the CUSTOM_INACTIVE_USER_ERROR can be a JSON document for example:

{
     "error": "in_active is set to false, can't update"
}

Thank you in advance.

Hi @loay_kh and welcome to MongoDB community forums!!

There could be multiple ways to resolve the issue which includes both handling the requirement from application end as well as from the database endpoint.

  1. Case: Writing query using conditional operator $cond in MongoDB:
[
    {
        '$match': {
            '_id': ObjectId('655ecae7c4b7864414582da9')
        }
    }, {
        '$project': {
            'error': {
                '$cond': {
                    'if': {
                        '$eq': [
                            '$is_active', False
                        ]
                    }, 
                    'then': 'user is not active, hence not updating the value', 
                    'else': None
                }
            }, 
            'occupation': {
                '$cond': {
                    'if': {
                        '$eq': [
                            '$is_active', True
                        ]
                    }, 
                    'then': 'Developer', 
                    'else': '$occupation'
                }
            }
        }
    }, {
        '$unset': 'error'
    }
]

Case 2: Using the $switch case operator:

[
  {
    $match:
      /**
       * query: The query in MQL.
       */
      {
        _id: ObjectId("655ecae7c4b7864414582da9"),
      },
  },
  {
    $addFields: {
      updatedOccupation: null,
    },
  },
  {
    $project:
      /**
       * specifications: The fields to
       *   include or exclude.
       */
      {
        updatedOccupation: {
          $switch: {
            branches: [
              {
                case: {
                  $eq: ["$is_active", true],
                },
                then: "Developer",
              },
              {
                case: {
                  $eq: ["$is_active", false],
                },
                then: "No occupation is set",
              },
            ],
          },
        },
        first_name: 1,
        last_name: 1,
        age: 1,
        occupation: 1,
        is_active: 1,
      },
  },
  {
    $unset:
      /**
       * Provide the field name to exclude.
       * To exclude multiple fields, pass the field names in an array.
       */
      "occupation",
  },
]

Case 3: Handling from the application end.

var userId = "65506e0b9ab7d8f1f9e23373";
var newOccupation = "Developer;

var result = db.users.findAndModify({
    query: { "_id": userId, "is_active": true },
    update: { $set: { "occupation": newOccupation } },
    new: true,
    fields: { "is_active": 1, "occupation": 1 }
});

if (!result) {
    printjson({ error: "User not found" });
} else if (!result.is_active) {
    printjson({ error: "Inactive user. Cannot update occupation." });
} else {
    printjson(result);
}

Please note that the aggregation and the code has been provided based on the sample data and the requirements mentioned. The recommendation would be to perform thorough testing before using on the production environment.

Regards
Aasawari