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
.