使用Slick 2.1.0构建动态查询

时间:2014-11-22 12:18:47

标签: scala slick slick-2.0

目标是使用可选关键字和/或shopId过滤项目。

如果没有定义,则应返回所有项目。

我的尝试是

case class ItemSearchParameters(keywords: Option[String], shopId: Option[Long])

def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
    try {
      db withDynSession {
        val q = Items.query
        if (params.keywords.isDefined) {
          q.filter { i =>
            ((i.title like "%" + params.keywords + "%")
            || (i.description like "%" + params.keywords + "%"))
          }
        }
        if (params.shopId.isDefined) {
          q.filter { i =>
            i.shopId === params.shopId
          }
        }
        Right(q.run.toList)
      }
    } catch {
      case e: SQLException =>
        Left(databaseError(e))
    }
  }

params.keywords或params.ShopId定义此函数返回所有Items。有人可以解释一下是什么问题吗?


更新:第二次尝试

def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
    try {
      db withDynSession {
        var q = Items.query
        q = params.keywords.map{ k => q.filter(_.title like "%" + k + "%")} getOrElse q
        q = params.keywords.map{ k => q.filter(_.description like "%" + k + "%")} getOrElse q
        q = params.shopId.map{ sid => q.filter(_.shopId === sid)} getOrElse q
        Right(q.run.toList)
      }
    } catch {
      case e: SQLException =>
        Left(databaseError(e))
    }
  }

对于第二次尝试,如果关键字是定义的,如何做(标题或描述)?


更新:使用MaybeFilter进行第三次尝试

case class MaybeFilter[X, Y](val query: scala.slick.lifted.Query[X, Y, Seq]) {
  def filteredBy(op: Option[_])(f:(X) => Column[Option[Boolean]]) = {
    op map { o => MaybeFilter(query.filter(f)) } getOrElse { this }
  }
}


class ItemDAO extends Configuration {

  implicit def maybeFilterConversor[X,Y](q:Query[X,Y,Seq]) = new MaybeFilter(q)

  def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
    try {
      db withDynSession {
        val q = Items
          .filteredBy(params.keywords){i => ((i.title like "%" + params.keywords + "%")
            || (i.description like "%" + params.keywords + "%"))}
          .filteredBy(params.shopId){_.shopId === params.shopId}
          .query
        Right(q.list)
      }
    } catch {
      case e: SQLException =>
        Left(databaseError(e))
    }
  }
}

如果给出关键字,则第三次尝试返回空列表

2 个答案:

答案 0 :(得分:0)

def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
    try {
      db withDynSession {
        var q = Items.query

        q = params.keywords.map{ k => q.filter(
          i => (i.title like "%" + k + "%")
              || (i.description  like "%" + k + "%")
          )} getOrElse q

        q = params.shopId.map{ sid => q.filter(
          _.shopId === sid
          )} getOrElse q

        Right(q.run.toList)
      }
    } catch {
      case e: SQLException =>
        Left(databaseError(e))
    }
  }

由于 var q

,我不确定这是最佳答案

答案 1 :(得分:0)

据我所知,你想通过可选字段制作过滤器。 你的第二次尝试更接近现实,第一次尝试不正确,你将选项字段与非选项进行比较。在我写这篇回复时你已经回答了你自己的回答:)

我想向您推荐这个MaybeFilter https://gist.github.com/cvogt/9193220

或者这里是修改后的版本:https://github.com/neowinx/hello-slick-2.1-dynamic-filter/blob/master/src/main/scala/HelloSlick.scala#L3-L7

也许这可以帮助您以更通用的方式解决问题。