4

在 Vapor 3 中,您可以使用filter带有 SQLiteBinaryOperator 的方法,因此您可以使用 like 运算符创建查询。我试图在 Vapor 4 中做同样的事情,但找不到任何东西。这是我的代码

蒸气 4

func queryUserMovies(_ req: Request) throws -> Future<[Users]> {
    let title = req.parameters.get("title")!
    return Movies.query(on: req.db).filter(\.$title == title).first().unwrap(or:Abort(.notFound, reason: "There's no movie")).flatMap{ movie in
        return movie.$users.query(on: req.db).all()
    }
}

蒸气 3

func queryUserMovies(_ req: Request) throws -> Future<[Users]> {
    guard let movie = req.query[String.self, at: "movie"] else {
        throw Abort(.badRequest, reason: "Not such movie")
    }
    return Movies.query(on: req).filter(\.title, .like, movie).first().unwrap(or:Abort(.notFound, reason: "There's no movie")).flatMap{ movie in
        return movie.users.query(on: req).all()
    }
}

Vapor 4 中是否有类似的东西,还是我需要在 SQL 中执行原始查询?

4

4 回答 4

9

Vapor 4 中的等价物是:

func queryUserMovies(_ req: Request) throws -> Future<[Users]> {
    let title = try req.query.get(String.self, at: "title")
    return Movies.query(on: req.db)
        .filter(\.$title, .custom("ilike"), title)
        .first()
        .unwrap(or:Abort(.notFound, reason: "There's no movie"))
        .flatMap{ movie in
            return movie.$users.query(on: req.db).all()
    }
}

您甚至可以执行更广泛的搜索来查找包含该标题的任何内容:

.filter(\.$title, .custom("ilike"), "%\(title)%")
于 2020-08-26T16:25:31.510 回答
2

我只是遇到了同样的问题,但还有一个障碍!

设置是与Category关系连接的Machine关系,我想用一个表达式在Machine.nameCategory.name中搜索一个或多个搜索词的出现。

机器类别关系都有一个名称属性。)

search属于[String.SubSequence]类型,因此我们可以遍历多个搜索词关键字,这些关键字必须都出现在名称中的某个位置。

我的解决方案是:

return Machine
  .query(on: req.db)
  .join(Category.self, on: \Category.$id == \Machine.$category.$id)
  // For each search-term the must be at least one fit with Machine.name and/or Category.name
  .group(.and) {
    var result = $0
    for term in search.map({ "%\(String($0))%" }) {
      // One or both must fit the search-term ...
      result = result.group(.or) {
        $0
          // Does the Machine name fit?
          .filter(\Machine.$name, .custom("ilike"), term)
          // Does the Category.path name fit?
          .filter(
            DatabaseQuery.Field.path(
              Category.path(for: \Category.$name),
              schema: Category.schema
            ),
            DatabaseQuery.Filter.Method.custom("ilike"),
            DatabaseQuery.Value.bind(term)
          )
      }
    }
  }

如您所见,有两个.group(...)函数。外部组 ( .or ) 表示“对于每个搜索词,必须有一个合适的内部组规则”,而内部组 ( .or ) 表示“必须至少有一个合适的 Machine.name 或 Category.name”。

由于“joined-relation-filter”不支持.custom("ilike")我使用了我在这里找到的解决方法。

即使这个问题可能已经回答了,我花了一些时间来解决这个问题,并认为我可以在这里分享它。

于 2020-08-31T15:20:25.957 回答
1

包含操作符 ~~ 可用于此目的:

Movie.query(on: req).filter(\.$title ~~ movie)

它不区分大小写。

于 2020-08-25T21:24:42.510 回答
0

如果要进行不区分大小写的排序,可以这样做:

Movie.query(on: req).sort(.custom("lower(title)"))
于 2020-11-12T16:39:53.743 回答