Vapor 4 不区分大小写的查询
Vapor 4 case insensitive query
在 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 中执行原始查询?
有包含运算符 ~~,可用于此:
Movie.query(on: req).filter(\.$title ~~ movie)
是case-insensitive。
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)%")
我刚刚遇到了同样的问题,但还有一个障碍!
设置是 Machine 关系与 Category 关系相结合,我想搜索一个或多个 search-terms 在 Machine.name 和 Category.name 中用一个表达式。
(Machine 和 Category 关系都有一个 name 属性。)
search 属于类型 [String.SubSequence],因此我们可以遍历多个 search-term 关键字,它们必须全部出现在名称中的某处。
我的解决方案是:
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 = [=10=]
for term in search.map({ "%\(String([=10=]))%" }) {
// One or both must fit the search-term ...
result = result.group(.or) {
[=10=]
// 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) 说“对于每个 search-term 必须有一个适合的内组规则”和内组 (.or) 说“必须至少有一个配件 Machine.name 或 Category.name”。
因为 .custom("ilike") 不受“joined-relation-filter”支持,所以我使用了我发现的解决方法 here.
即使这个问题可能已经有了答案,但我花了一些时间来弄清楚这个问题,并认为我可以在这里分享它。
如果你想做不区分大小写的排序,你可以这样做:
Movie.query(on: req).sort(.custom("lower(title)"))
在 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 中执行原始查询?
有包含运算符 ~~,可用于此:
Movie.query(on: req).filter(\.$title ~~ movie)
是case-insensitive。
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)%")
我刚刚遇到了同样的问题,但还有一个障碍!
设置是 Machine 关系与 Category 关系相结合,我想搜索一个或多个 search-terms 在 Machine.name 和 Category.name 中用一个表达式。
(Machine 和 Category 关系都有一个 name 属性。)
search 属于类型 [String.SubSequence],因此我们可以遍历多个 search-term 关键字,它们必须全部出现在名称中的某处。
我的解决方案是:
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 = [=10=]
for term in search.map({ "%\(String([=10=]))%" }) {
// One or both must fit the search-term ...
result = result.group(.or) {
[=10=]
// 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) 说“对于每个 search-term 必须有一个适合的内组规则”和内组 (.or) 说“必须至少有一个配件 Machine.name 或 Category.name”。
因为 .custom("ilike") 不受“joined-relation-filter”支持,所以我使用了我发现的解决方法 here.
即使这个问题可能已经有了答案,但我花了一些时间来弄清楚这个问题,并认为我可以在这里分享它。
如果你想做不区分大小写的排序,你可以这样做:
Movie.query(on: req).sort(.custom("lower(title)"))