Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JAVA-5775 Filter null values in Filters.and / Filters.or #1618

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import com.mongodb.client.model.Filters
import com.mongodb.client.model.TextSearchOptions
import com.mongodb.client.model.geojson.Geometry
import com.mongodb.client.model.geojson.Point
import org.bson.BsonDocument
import org.bson.BsonType
import org.bson.conversions.Bson
import java.util.regex.Pattern
import kotlin.internal.OnlyInputTypes
import kotlin.reflect.KProperty
import org.bson.BsonType
import org.bson.conversions.Bson

/**
* Filters extension methods to improve Kotlin interop
Expand Down Expand Up @@ -288,7 +289,7 @@ public object Filters {
* @param filters the list of filters to and together
* @return the filter
*/
public fun and(filters: Iterable<Bson?>): Bson = Filters.and(filters)
public fun and(filters: Iterable<Bson?>): Bson = combineFilters(Filters::and, filters)

/**
* Creates a filter that performs a logical AND of the provided list of filters. Note that this will only generate
Expand All @@ -309,7 +310,7 @@ public object Filters {
* @param filters the list of filters to and together
* @return the filter
*/
public fun or(filters: Iterable<Bson?>): Bson = Filters.or(filters)
public fun or(filters: Iterable<Bson?>): Bson = combineFilters(Filters::or, filters)

/**
* Creates a filter that preforms a logical OR of the provided list of filters.
Expand Down Expand Up @@ -352,7 +353,9 @@ public object Filters {
*
* @return the filter
*/
@JvmSynthetic @JvmName("existsExt") public fun <T> KProperty<T?>.exists(): Bson = Filters.exists(path())
@JvmSynthetic
@JvmName("existsExt")
public fun <T> KProperty<T?>.exists(): Bson = Filters.exists(path())

/**
* Creates a filter that matches all documents that contain the given property.
Expand Down Expand Up @@ -1216,4 +1219,18 @@ public object Filters {
* @return the filter
*/
public fun jsonSchema(schema: Bson): Bson = Filters.jsonSchema(schema)

private fun combineFilters(
combine: (List<Bson>) -> Bson,
filters: Iterable<Bson?>
): Bson = filters
.filterNotNull()
.filterNot { bson -> bson is Map<*, *> && bson.isEmpty() }
.let { list ->
when (list.size) {
0 -> BsonDocument()
1 -> list.first()
else -> combine(list)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,18 @@ class FiltersTest {
@Test
fun testOrSupport() {
val expected = BsonDocument.parse("""{${'$'}or: [{"name": "Ada"}, {"age": 20 }]}""")

val bson = or(eq(Person::name, person.name), eq(Person::age, person.age))
assertEquals(expected, bson.document)

val kmongoDsl = or(Person::name eq person.name, Person::age eq person.age)
assertEquals(expected, kmongoDsl.document)

val bsonWithNull = or(eq(Person::name, person.name), eq(Person::age, person.age), null)
assertEquals(expected, bsonWithNull.document)

val kmongoDslWithNull = or(Person::name eq person.name, Person::age eq person.age, null)
assertEquals(expected, kmongoDslWithNull.document)
}

@Test
Expand All @@ -186,11 +193,18 @@ class FiltersTest {
@Test
fun testAndSupport() {
val expected = BsonDocument.parse("""{${'$'}and: [{"name": "Ada"}, {"age": 20 }]}""")

val bson = and(eq(Person::name, person.name), eq(Person::age, person.age))
assertEquals(expected, bson.document)

val kmongoDsl = and(Person::name.eq(person.name), Person::age.eq(person.age))
assertEquals(expected, kmongoDsl.document)

val bsonWithNull = and(eq(Person::name, person.name), eq(Person::age, person.age), null)
assertEquals(expected, bsonWithNull.document)

val kmongoDslWithNull = and(Person::name.eq(person.name), Person::age.eq(person.age), null)
assertEquals(expected, kmongoDslWithNull.document)
}

@Test
Expand Down