将 map 传递给 slick filter 并按 map 中的值进行过滤

Pass map to slick filter and filter by the values in the map

我是 scala 的新手,我正在尝试将地图即 Map[String, Any]("from_type" -> "Admin", "from_id" -> 1) 传递到我的服务以进行动态过滤。我试图避免像这样编写我的代码 filter(_.fromType === val && _.fromId === val2)

尝试这个例子时Slick dynamically filter by a list of columns and values

我发现类型不匹配。 Required Function1[K, NotInfered T]Found: Rep[Boolean]

服务代码:

val query = TableQuery[UserTable]

def all(perPage: Int page: Int, listFilters: Map[String, Any]): Future[ResultPagination[User]] = {

  val baseQuery = for {
   items <- query.filter( listFilters ).take(perPage).drop(page).result // <----I want to filter here
    total <- query.length.result
  } yield ResultPagination[User](items, total)
  db.run(baseQuery)
}

Table代码:

def fromId: Rep[Int] = column[Int]("from_id")
def fromType: Rep[String] = column[String]("from_type")

def columnToRep(column: String): Rep[_] = {
  column match {
    case "from_type" = this.fromType
    case "from_id" = this.fromId
   }
}

好吧,我不建议使用 Map[String, Any] 构造,因为使用 Any 你会失去类型安全:例如你可以错误地传递给函数 Map("fromId" -> "1") 和编译无助于识别问题。

我猜,你想要的是传递某种表示变量过滤器的结构。在这种情况下,Query.filterOpt 可以为您提供帮助。您可以查看用法示例:https://scala-slick.org/doc/3.3.2/queries.html#sorting-and-filtering

请看下面的代码示例:

  // Your domain filter structure. None values will be ignored
  // So `UserFilter()` - will match all.
  case class UserFilter(fromId: Option[Int] = None, fromString: Option[String] = None)

  def all(perPage: Int, page: Int, filter: UserFilter): Future[ResultPagination[User]] = {
    val baseQuery = for {
      items <- {
        query
          .filterOpt(filter.fromId)(_.fromId === _)
          .filterOpt(filter.fromString)(_.fromType === _)
          .take(perPage)
          .drop(page)
          .result
      }
      total <- query.length.result
    } yield ResultPagination[User](items, total)
    db.run(baseQuery)
  }

这将是安全的。 希望这对您有所帮助!