Skip to content

MongoDB request DSLopensavvy.ktmongo.dsl.treeAbstractBsonNode

AbstractBsonNode

abstract class AbstractBsonNode : Node, BsonNode

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. <strong>$and</strong>), 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

AbstractBsonNode

constructor(context: )

Types

Companion

object Companion

Properties

context

open override val context: 

The context used to generate this expression.

Functions

freeze

open override fun freeze()

Makes this node immutable.

simplify

open override fun simplify(): AbstractBsonNode?

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

toBson

open fun toBson(): 

Writes the result of simplifying to a new Bson.

toString

override fun toString(): String

JSON representation of this expression.

fun toString(simplified: Boolean): String

JSON representation of this expression.

writeTo

override fun writeTo(writer: )

Writes the result of simplifying this expression into writer.