MongoDB $ln

In MongoDB, the $ln aggregation pipeline operator calculates the natural logarithm (ln) of a number and returns the result as a double.

Syntax

The syntax goes like this:

{ $ln: <number> }

Where <number> can be any valid expression that resolves to a non-negative number.

Example

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

{ "_id" : 1, "data" : 0.5 }
{ "_id" : 2, "data" : 20 }
{ "_id" : 3, "data" : 200 }

We can use the $ln operator to return the natural logarithm of the data field:

db.test.aggregate(
  [
    { $match: { _id: { $in: [ 1, 2, 3 ] } } },
    {
      $project:
        { 
          _id: 0,
          data: 1,
          result: { $ln: [ "$data" ] }
        }
    }
  ]
)

Result:

{ "data" : 0.5, "result" : -0.6931471805599453 }
{ "data" : 20, "result" : 2.995732273553991 }
{ "data" : 200, "result" : 5.298317366548036 }

Another way of doing this would have been to use the $log operator with a second argument of Math.E. See MongoDB $log for an example.

Natural Logarithm

The natural logarithm of a number is its logarithm to the base of the mathematical constant e, where e is an irrational and transcendental number that starts off with 2.7182818284590452353602874713527 and continues on forever.

The mathematical constant e is also known as Euler’s number.

In JavaScript, we can use Math.E to represent e. We can therefore get the natural logarithm of e by using Math.E as the argument when using $ln.

Suppose we have a document like this:

{ "_id" : 4, "data" : 2.718281828459045 }

The data field contains e to 15 decimal places.

This example uses two ways to return the natural logarithm of e:

db.test.aggregate(
  [
    { $match: { _id: { $in: [ 4 ] } } },
    {
      $project:
        { 
          _id: 0,
          e_1: { $ln: [ "$data" ] },
          e_2: { $ln: [ Math.E ] }
        }
    }
  ]
)

Result:

{ "e_1" : 1, "e_2" : 1 }

The first result uses the data from the document. For the second result, we use Math.E to generate e.

Either way, the result is 1.

Out of Range Values

As mentioned, the $ln operator accepts any valid expression that resolves to a non-negative number. Values outside of that range will cause an error.

Suppose we add the following document to our collection:

{ "_id" : 5, "data" : -20 }

Let’s run the the $ln operator against that document:

db.test.aggregate(
  [
    { $match: { _id: { $in: [ 5 ] } } },
    {
      $project:
        { 
          _id: 0,
          data: 1,
          result: { $ln: [ "$data" ] }
        }
    }
  ]
)

Result:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$ln's argument must be a positive number, but is -20",
	"code" : 28766,
	"codeName" : "Location28766"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1

Wrong Data Type

Providing the wrong data type will also cause an error.

Suppose we add the following document to our collection:

{ "_id" : 6, "data" : "Ten" }

Let’s run the the $ln operator against that document:

db.test.aggregate(
  [
    { $match: { _id: { $in: [ 6 ] } } },
    {
      $project:
        { 
          _id: 0,
          data: 1,
          result: { $ln: [ "$data" ] }
        }
    }
  ]
)

Result:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$ln only supports numeric types, not string",
	"code" : 28765,
	"codeName" : "Location28765"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1

We provided a string, and so the error message tells us that $ln only supports numeric types, not string.

Null Values

Null values return null when using the $ln operator.

Suppose we add the following document to our collection:

{ "_id" : 7, "data" : null }

Let’s run the the $ln operator against that document:

db.test.aggregate(
  [
    { $match: { _id: { $in: [ 7 ] } } },
    {
      $project:
        { 
          _id: 0,
          data: 1,
          result: { $ln: [ "$data" ] }
        }
    }
  ]
)

Result:

{ "data" : null, "result" : null }

We can see that the result is null.

NaN Values

If the argument resolves to NaN$ln returns NaN.

Example:

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

Result:

{ "data" : 0.5, "result" : NaN }

Non-Existent Fields

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

Example:

db.test.aggregate(
  [
    { $match: { _id: { $in: [ 1 ] } } },
    {
      $project:
        { 
          _id: 0,
          data: 1,
          result: { $ln: [ "$age" ] }
        }
    }
  ]
)

Result:

{ "data" : 0.5, "result" : null }

In this case we tried to apply $ln against a field called age, but that field doesn’t exist in the document, and so we get null.