AbstractBsonNode

Utility implementation for BsonNode, which handles the context, toString representation and freezing.

Implementing a new operator

Instances of this class are BSON operators, like $eq, $xor, $setOnInsert and $lookup.

Custom operators bypass the entirety of the safety features provided by this library. Because they are able to write arbitrary BSON, no checks whatsoever are possible. If you are not careful, this may make injection attacks or data leaking possible.

Before writing your own operator, familiarize yourself with the documentation of BsonNode, AbstractBsonNode, CompoundBsonNode and AbstractCompoundBsonNode, as well as BsonFieldWriter.

Fundamentally, an operator is anything that is able to write itself into a BSON document. Operators should not be mutable, except through their accept method (if they have one).

An operator generally looks like the following:

@LowLevelApi
private class TypePredicateExpressionNode(
val type: BsonType,
context: BsonContext,
) : AbstractBsonNode(context) {

override fun write(writer: BsonFieldWriter) {
writer.writeInt32("\$type", type.code)
}
}

The BsonContext is required at construction because it is needed to implement toString, which the user could call at any time, including while the operator is being constructed (e.g. when using a debugger). It is extremely important that the toString representation they see is consistent with the final BSON sent over the wire.

Once you have created your operator, use the accept method to register it into a DSL:

collection.find {
User::name {
accept(TypePredicateExpressionNode(BsonType.Undefined))
}
}

Of course, the operator described above is already made available: FilterQueryPredicate.hasType.

Note that if your operator accepts a variable number of sub-expressions (e.g. $and), you must ensure that it works for any number of expressions, including 1 and 0. See simplify.

To create an operator that can accept multiple children operators (for example $and), implement AbstractCompoundBsonNode.

Since operators are complex to write, risky to get wrong, and hard to test, we highly recommend to upstream any operator you create so they can benefit from future fixes. Again, an improperly-written operator may allow data corruption or leaking.

Operators should preferably be immutable. To create mutable operators, prefer using AbstractCompoundBsonNode. Note that once frozen is true, operators must be immutable forever, or other features of this library will break.

Inheritors

Constructors

Link copied to clipboard
constructor(context: <Error class: unknown class>)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
open override val context: <Error class: unknown class>

The context used to generate this expression.

Functions

Link copied to clipboard
open override fun freeze()

Makes this node immutable.

Link copied to clipboard
open override fun simplify(): AbstractBsonNode?

Returns a simplified (but equivalent) expression to the current expression.

Link copied to clipboard
open fun toBson(): <Error class: unknown class>

Writes the result of simplifying to a new Bson.

Link copied to clipboard
override fun toString(): String
fun toString(simplified: Boolean): String

JSON representation of this expression.

Link copied to clipboard
override fun writeTo(writer: <Error class: unknown class>)

Writes the result of simplifying this expression into writer.