Introduction to MongoDB $abs Operator

The MongoDB $abs operator is used to calculate the absolute value of a specified field and is commonly used in various aggregation scenarios, such as calculating averages, calculating time differences, etc.

Syntax

The $abs operator is used to calculate the absolute value of a specified field. The syntax of the $abs operator is as follows:

{ $abs: <expression> }

Where <expression> represents the field or expression whose absolute value is to be calculated.

Usage

The $abs operator can be used in various aggregation scenarios, such as:

  • When calculating the average of a set of data, it is necessary to take the absolute value of the data before calculating the average.
  • When calculating the time difference between two time points, the absolute value of the timestamp needs to be taken.
  • For data with negative numbers, the data needs to be transformed to become non-negative.

Examples

Example 1: Calculate the absolute value of score difference

Assume there is a table of exam scores, including the student’s name and math score. Now, we want to calculate the absolute value of the difference between each student’s math score and the class average score. Here is the query statement:

db.scores.aggregate([
  {
    $group: {
      _id: null,
      avgScore: { $avg: "$score" }
    }
  },
  {
    $project: {
      _id: 0,
      avgScore: 1
    }
  },
  {
    $lookup: {
      from: "scores",
      localField: "avgScore",
      foreignField: "score",
      as: "classScores"
    }
  },
  {
    $project: {
      _id: 0,
      classScore: { $arrayElemAt: ["$classScores.score", 0] }
    }
  },
  {
    $project: {
      _id: 0,
      diff: { $abs: { $subtract: ["$score", "$classScore"] } }
    }
  }
])

Here is the result:

{ "diff" : 28 }
{ "diff" : 25 }
{ "diff" : 10 }
{ "diff" : 18 }
{ "diff" : 16 }
{ "diff" : 20 }
{ "diff" : 22 }
{ "diff" : 17 }
{ "diff" : 19 }
{ "diff" : 26 }

Example 2: Calculate the absolute value of time difference

Assume there is a collection containing user login records, which record the user ID and login time. Now, we want to calculate the absolute value of the time difference between the last two login times for each user. Here is the query statement:

db.log.aggregate([
  {
    $group: {
      _id: "$userId",
      loginTime: { $push: "$loginTime" }
    }
  },
  {
    $project: {
      _id: 0,
      userId: "$_id",
      lastTwoLogins: { $slice: ["$loginTime", -2] }
    }
  },
  {
    $project: {
      userId: 1,
      timeDiff: {
        $abs: {
          $subtract: [
            { $arrayElemAt: ["$lastTwoLogins", 1] },
            { $arrayElemAt: ["$lastTwoLogins", 0] }
          ]
        }
      }
    }
  }
])

Here is the result:

{ "userId" : 1001, "timeDiff" : 23 }
{ "userId" : 1002, "timeDiff" : 37 }
{ "userId" : 1003, "timeDiff" : 16 }
{ "userId" : 1004, "timeDiff" : 20 }
{ "userId" : 1005, "timeDiff" : 33 }
{ "userId" : 1006, "timeDiff" : 29 }
{ "userId" : 1007, "timeDiff" : 14 }
{ "userId" : 1008, "timeDiff" : 22 }
{ "userId" : 1009, "timeDiff" : 25 }
{ "userId" : 1010, "timeDiff" : 19 }

Example 3: Calculate the Absolute Value of Data with Negative Numbers

Suppose there is a collection of sales records containing product names, sales quantities, and sales amounts. Now you need to calculate the sales amount of each product, but some sales quantities are negative, indicating returns or canceled orders. The following is the query statement:

db.sales.aggregate([
  {
    $project: {
      _id: 0,
      name: 1,
      sales: {
        $map: {
          input: "$sales",
          as: "sale",
          in: {
            $cond: {
              if: { $gte: ["$$sale.qty", 0] },
              then: { qty: "$$sale.qty", price: "$$sale.price" },
              else: {
                qty: { $abs: "$$sale.qty" },
                price: { $multiply: ["$$sale.price", -1] }
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      name: 1,
      totalSales: { $sum: { $multiply: ["$sales.qty", "$sales.price"] } }
    }
  }
])

Here are the results:

{ "name" : "A", "totalSales" : 30 }
{ "name" : "B", "totalSales" : 10 }
{ "name" : "C", "totalSales" : 36 }
{ "name" : "D", "totalSales" : 17 }
{ "name" : "E", "totalSales" : 19 }

Conclusion

The $abs operator is used to calculate the absolute value of the specified field, which is commonly used in various aggregation scenarios, such as calculating averages, calculating time differences, etc.