MongoDB $pow

In MongoDB, the $pow aggregation pipeline operator raises a number to the specified exponent and returns the result

$pow accepts two expressions, supplied in an array. The first one is the number, and the second is the exponent. Both can be any valid expression, as long as they resolve to a number.

Example

Suppose we have a collection called test with the following documents:

{ "_id" : 1, "data" : 10 }
{ "_id" : 2, "data" : -3 }
{ "_id" : 3, "data" : 0 }
{ "_id" : 4, "data" : null }

We can use the $pow operator to raise the data field by a specified exponent:

db.test.aggregate(
  [
    { $project: { 
        _id: 0,
        result: { $pow: [ "$data", 3 ] }
      }
    }
  ]
)

Result:

{ "result" : 1000 }
{ "result" : -27 }
{ "result" : 0 }
{ "result" : null }

In this case, I used the data field as the number, and 3 as the exponent. Therefore, each document had its data field raised by the power of 3.

We can see that null values return null.

The result is usually the same type as the input. However, there are exceptions to this rule. Specifically:

  • A 32-bit integer will be converted to a 64-bit integer if the result is representable as a 64-bit integer.
  • A 32-bit integer will be converted to a double if the result is not representable as a 64-bit integer.
  • A 64-bit integer will be converted to double if the result is not representable as a 64-bit integer.

Negative Exponent

You cannot raise zero (0) to a negative exponent.

Example:

db.test.aggregate(
  [
    { $match: { _id: 3 } },
    { $project: { 
        _id: 0,
        result: { $pow: [ "$data", -3 ] }
      }
    }
  ]
)

Result:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$pow cannot take a base of 0 and a negative exponent",
	"code" : 28764,
	"codeName" : "Location28764"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:618:17
assert.commandWorked@src/mongo/shell/assert.js:708:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1046:12
@(shell):1:1

The error explicitly states that “$pow cannot take a base of 0 and a negative exponent“.

However, if we exclude document 3, we no longer get the error:

db.test.aggregate(
  [
    { $match: { _id: { $nin: [ 3 ] } } },
    { $project: { 
        result: { $pow: [ "$data", -3 ] }
      }
    }
  ]
)

Result:

{ "_id" : 1, "result" : 0.001 }
{ "_id" : 2, "result" : -0.037037037037037035 }
{ "_id" : 4, "result" : null }

NaN Values

If the argument resolves to NaN$pow returns NaN.

Example:

db.test.aggregate(
  [
    { $project: { 
        _id: 0,
        result: { $pow: [ "$data" * 1, 3 ] }
      }
    }
  ]
)

Result:

{ "result" : NaN }
{ "result" : NaN }
{ "result" : NaN }
{ "result" : NaN }

Non-Existent Fields

If the $pow operator is applied against a field that doesn’t exist, null is returned.

Example:

db.test.aggregate(
  [
    { $project: { 
        _id: 0,
        result: { $pow: [ "$beer", 3 ] }
      }
    }
  ]
)

Result:

{ "result" : null }
{ "result" : null }
{ "result" : null }
{ "result" : null }

Null Exponent

We’ve already seen that a null value returns null. This is also true when providing null as the exponent.

Example:

db.test.aggregate(
  [
    { $project: { 
        _id: 0,
        result: { $pow: [ "$data", null ] }
      }
    }
  ]
)

Result:

{ "result" : null }
{ "result" : null }
{ "result" : null }
{ "result" : null }