Unable to query Mongo with Kotlin nullable List

36 Views Asked by At

I am in process of converting a Java (Jersey) application to a Kotlin (Spring Boot) application. I used IntelliJ's built in Java to Kotlin converter to do the conversion. Most of my Kotlin models ended up with optional properties (most of them are necessary).

For example following class Workflow has a property called taskIds which is of type MutableList<ObjectId>?.

class Workflow {
    @JsonSerialize(using = ListObjectIdJsonSerializer::class)
    var taskIds: MutableList<ObjectId>? = null
}

My problem is when I query MongoDB database with a filter that contains the taskIds, it doesn't return any results even though I see the Documents corresponding to the filter exists on the DB. Following is the code snippet of the method call that query the DB.

// Following doesnot work as Filters.in expect a ArrayList not ArrayList?
tasksDAO.getTasks(Filters.`in`("_id", workflow.taskIds))

// Internally above getTask calls
// mongoClient.getDatabase("dbname").getCollection<Workflow>("workflows", Workflow::class.java).find(filter)

Further investigating the issue by printing the filter with filter.toBsonDocument().toString(), I notice that $in filter's value was of type array of arrays (i.e. [[ObjectId,...]]. I expected it to be a just an array of Objects (I.e. [ObjectId,..]).

{
  "_id": {
    "$in": [
      [
        {
          "$oid": "657f9c8c1f6f30131a7c6cc8"
        },
        {
          "$oid": "657f9c8c1f6f30131a7c6cc9"
        },
        {
          "$oid": "657f9c8c1f6f30131a7c6cca"
        }
      ]
    ]
  }
}

However, If I force unwrap the taskIds (i.e. workflow.taskIds!!) and called the same method, Mongo returns list of documents properly. Following is the code related to force unwrapped query and the filter as a BsonDocument string.

// Following does work since it force unwrapping the ArrayList? to ArrayList
tasksDAO.getTasks(Filters.`in`("_id", workflow.taskIds!!))
{
  "_id": {
    "$in": [
      {
        "$oid": "657f9c8c1f6f30131a7c6cc8"
      },
      {
        "$oid": "657f9c8c1f6f30131a7c6cc9"
      },
      {
        "$oid": "657f9c8c1f6f30131a7c6cca"
      }
    ]
  }
}

My question: Is there anyway for me to pass in the taskIds to the $in filter and get corresponding Documents from the DB without me force unwrapping it?

The reason I don't want to force unwrap

  1. I might make a mistake in the future and just pass in an optional such as List<String>?. Since there is no warning or error, it might linger for while without me noticing it.
  2. I have a lots of optional fields on the code base and its very hard to go though all of them
0

There are 0 best solutions below