Reputation: 69
Here I filter the table by 1 column(keyId) and 1 value(keyId), and result type is Optional, it's correct.
override def findByKeyId(keyId: String): Future[Option[Event]] =
db.run(events.filter(_.keyId === keyId).result.headOption)
Now I need filter by 1 column(keyId) and multiple values.
override def findByKeyIdBulk(keyIdSeq: Seq[Option[String]]): Future[Seq[Option[Event]]] = {
db.run(
events.filter { event =>
keyIdSeq
.map(_.map(keyId => event.keyId === keyId))
.collect({ case Some(criteria) => criteria })
.reduceLeftOption(_ || _)
.getOrElse(true: Rep[Boolean])
}.result
) // Future[Seq[Event]]
}
In this code expression of type Future[Seq[Event]]
doesn't conform to
Future[Seq[Option[Event]]]
How to fix?
Upvotes: 1
Views: 709
Reputation: 524
I think you misunderstand the point of having Option[T]
as a return value. Returning Seq[Option[T]]
is anti-pattern and here is why:
Option[T]
makes total sense when there is no guarantee that you'll find anything. FindById is a great example where it is useful - we either find something and get Some(value)
or we don't and get None
.
But if you are planning to find by several ids and want a Seq
of found values, then there are two cases: either Seq
is empty and nothing was found or Seq
contains some elements. There is no point in having Option[T]
inside Seq
because there won't be any None
s inside the sequence. You'll be forced to use an extra pattern matching or extra map which is totally pointless.
I think you will be better off changing type signature to Future[Seq[Event]]
Upvotes: 2
Reputation: 22625
Calling events.result
will result in returning Future[Seq[Event]]
. Using filter
won't change that, so the resulting type is still Future[Seq[Event]]
. In order to change it to Future[Seq[Option[Event]]]
you'd have to lift values to Option[Event]
:
db.run(
events.filter { event =>
keyIdSeq
.map(_.map(keyId => event.keyId === keyId))
.collect({ case Some(criteria) => criteria })
.reduceLeftOption(_ || _)
.getOrElse(true: Rep[Boolean])
}
.map(_.map(Option(_))) //lifting Event to Option[Event]
.result
) // Future[Seq[Option[Event]]]
Upvotes: 1