使用Slick进行多重或过滤

时间:2019-05-04 16:48:18

标签: postgresql scala slick

这里我用1列(keyId)和1个值(keyId)过滤表,结果类型为Optional,是正确的。

public class Example extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent i = new Intent(context, Main.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    }
}

现在我需要按1列(keyId)和多个值进行过滤。

override def findByKeyId(keyId: String): Future[Option[Event]] =
    db.run(events.filter(_.keyId === keyId).result.headOption)

在此代码类型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]] } 中的表达式不符合 Future[Seq[Event]]

如何解决?

2 个答案:

答案 0 :(得分:2)

我认为您误解了将Option[T]作为返回值的意义。返回Seq[Option[T]]是反模式,这是原因:

如果不能保证找到任何东西,那么

Option[T]就很有意义。 FindById是一个很好的例子,它很有用-我们要么找到某个东西并获取Some(value),要么不获取某个东西None

但是,如果您打算通过多个ID进行查找并希望找到一个Seq的找到的值,则有两种情况:Seq为空且未找到任何内容或Seq包含一些要素。在Option[T]中包含Seq是没有意义的,因为序列中不会有任何None。您将不得不使用额外的模式匹配或完全没有意义的地图。

我认为您最好将类型签名更改为Future[Seq[Event]]

答案 1 :(得分:1)

呼叫Future[Seq[Event]]将导致返回filter。使用Future[Seq[Event]]不会改变它,因此结果类型仍然是Future[Seq[Option[Event]]]。为了将其更改为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]]]

library(wooldridge)
library(dplyr)
data("gpa1")
# View(gpa1)

df <- gpa1 %>% 
  dplyr::filter(job19 == 1) 
head(df, 10)