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
Properties
Functions
Returns a simplified (but equivalent) expression to the current expression.
Writes the result of simplifying to a new Bson.
Writes the result of simplifying this expression into writer.