Skip to main content

MongoDB Driver Integration

The criteria4s-mongodb-driver module bridges criteria4s with the official MongoDB Java/Scala driver. It provides extension methods and implicit conversions that turn a Criteria[MongoDB] directly into a Bson filter document, so you can pass your type-safe criteria straight into the driver's find() or aggregation methods.

Dependency

libraryDependencies += "com.eff3ct" %% "criteria4s-mongodb-driver" % "1.0.0"

This module transitively depends on criteria4s-mongodb and the MongoDB driver sync (org.mongodb:mongodb-driver-sync).

Import Pattern

import com.eff3ct.criteria4s.core.*
import com.eff3ct.criteria4s.dialect.mongodb.{*, given}
import com.eff3ct.criteria4s.dialect.mongodb.driver.given
import com.eff3ct.criteria4s.functions as F
import com.eff3ct.criteria4s.extensions.*

The key import is com.eff3ct.criteria4s.dialect.mongodb.driver.given, which brings in .toBson, .toBsonDocument, and the implicit Conversion[Criteria[MongoDB], Bson].

API

.toBson

Converts a criteria to a Bson filter document:

val filter: Criteria[MongoDB] = F.col[MongoDB]("age").geq(F.lit[MongoDB, Int](18))
val bson: Bson = filter.toBson

.toBsonDocument

Converts a criteria to a BsonDocument (a more specific type):

val doc: BsonDocument = filter.toBsonDocument

Implicit Conversion to Bson

The driver package provides a given Conversion[Criteria[MongoDB], Bson], so you can pass criteria directly wherever Bson is expected — no explicit conversion needed:

import com.eff3ct.criteria4s.dialect.mongodb.driver.given

val filter: Criteria[MongoDB] = F.col[MongoDB]("age").geq(F.lit[MongoDB, Int](18))
collection.find(filter) // Criteria[MongoDB] converts to Bson automatically

JSON Normalization

The MongoDB expression dialect renders $-prefixed operators without surrounding quotes for readability (e.g., $eq, $gte). The driver integration automatically normalizes these to valid Extended JSON before parsing, quoting all $-prefixed operators. For example:

  • Input: {"age": {$gte: 18}}
  • Normalized: {"age": {"$gte": 18}}

This normalization happens transparently when calling .toBson, .toBsonDocument, or using the implicit conversion.

Example with MongoCollection

The following example shows how to use criteria4s with the MongoDB driver. This is a plain code example since the MongoDB driver is not available in the docs classpath.

import com.mongodb.client.{MongoClients, MongoCollection}
import org.bson.Document
import com.eff3ct.criteria4s.core.*
import com.eff3ct.criteria4s.dialect.mongodb.{*, given}
import com.eff3ct.criteria4s.dialect.mongodb.driver.given
import com.eff3ct.criteria4s.functions as F
import com.eff3ct.criteria4s.extensions.*

val client = MongoClients.create("mongodb://localhost:27017")
val database = client.getDatabase("mydb")
val collection = database.getCollection("users")

// Build a type-safe filter
val filter = F.col[MongoDB]("age")
.geq(F.lit[MongoDB, Int](21))
.and(F.col[MongoDB]("status") === F.lit[MongoDB, String]("active"))
.and(F.col[MongoDB]("deleted_at").isNull)

// Use directly with find() -- implicit conversion to Bson
val results = collection.find(filter)

results.forEach { doc =>
println(s"${doc.getString("name")}: ${doc.getInteger("age")}")
}

// Or use .toBson explicitly
val explicitBson = filter.toBson
val results2 = collection.find(explicitBson)

client.close()

Combining with Aggregation Pipelines

You can also use criteria as a $match stage in aggregation pipelines by converting to Bson explicitly:

import com.mongodb.client.model.Aggregates

val matchStage = Aggregates.`match`(filter.toBson)
val pipeline = java.util.List.of(matchStage)
val aggResults = collection.aggregate(pipeline)