Vapor升级到Vapor3的时间恰巧赶上WWDC,本来想从美国回来就开始写一些关于Vapor3的文章,但是WWDC信息量太大了,直到现在才转过来写一点关于Vapor的东西。
这篇文章主要介绍如何使用Fluent查询数据,后面我会补上如何配置相关的教程。
Fluent为我们提供了一个Model类, MySQLModel、 PostgreSQLModel、SQLiteModel均继承自这个类。在Model的一个extension中,Flunt为我们提供了一个query方法并返回 QueryBuilder<Self.Database, Self>
下面,我们再看看这个QueryBuilder:
QueryBuilder<Self.Database, Self>
这个QueryBuilder会含有Model的类型,数据库类型,利用这些信息来连接数据库进行查询。
现在有了这个QueryBuilder了,下面就可以利用它来进行查询操作了:
为了简化对问题的理解,这里提供一个最简单的Model来验证:
import FluentMySQL
import Vapor
/// A single entry of a Todo list.
final class Todo: Codable {
/// The unique identifier for this `Todo`.
var id: Int?
/// A title describing what this `Todo` entails.
var title: String
/// Creates a new `Todo`.
init(id: Int? = nil, title: String) {
self.id = id
self.title = title
}
}
extension Todo: MySQLModel { }
/// Allows `Todo` to be used as a dynamic migration.
extension Todo: Migration { }
/// Allows `Todo` to be encoded to and decoded from HTTP messages.
extension Todo: Content { }
/// Allows `Todo` to be used as a dynamic parameter in route definitions.
extension Todo: Parameter { }
可以看到这里的Todo类只含有一个id和title,而id由mysql数据库自动生成,只需要传入一个title则可以添加一条记录。
查询所有记录
Todo.query(on: req).all()
查询title为'work'的记录
try Todo.query(on: req).filter(\.title == "work" ).all()
查询title不为'work'的记录
try Todo.query(on: req).filter(\.title != "work" ).all()
查询id大于5的记录
try Todo.query(on: req).filter(\.id > 5 ).all()
查询id小于5的记录
try Todo.query(on: req).filter(\.id < 5 ).all()
查询id大于等于5的记录
try Todo.query(on: req).filter(\.id >= 5 ).all()
查询id小于等于5的记录
try Todo.query(on: req).filter(\.id <= 5 ).all()
查询id为 5、7、11的数据
try Todo.query(on: req).filter(\.id ~~ [5, 7, 11]).all()
查询id不为 5、7、11的数据
try Todo.query(on: req).filter(\.id !~ [5, 7, 11]).all()
模糊查询
查询title前缀为‘work’的数据
Todo.query(on: req).filter(\.title, .like, "work%").all()
查询title后缀为‘work’的数据
Todo.query(on: req).filter(\.title, .like, "%work").all()
查询title包含‘work’的数据
Todo.query(on: req).filter(\.title, .like, "%work%").all()
如果只查询一条数据
Todo.query(on: req).filter(\.title, .like, "%work%").first()
如果什么都查不出来,则会返回nil
其实模糊查询也有提供类似于 ==, !=, >, <这样的操作符,但是经过测试并没有达到比较好的效果,所以这里的demo只是展示目前我测试可用的方法,如果未来能够支持的更好,我会再补充。
更多查询方法:
《SQL》库中的GenericSQLBinaryOperator包含sql中需要的操作符,这里贴出部分源码一看究竟:
/// See `SQLSerializable`.
public func serialize(_ binds: inout [Encodable]) -> String {
switch self {
case ._add: return "+"
case ._bitwiseAnd: return "&"
case ._bitwiseOr: return "|"
case ._bitwiseShiftLeft: return "<<"
case ._bitwiseShiftRight: return ">>"
case ._concatenate: return "||"
case ._divide: return "/"
case ._equal: return "="
case ._greaterThan: return ">"
case ._greaterThanOrEqual: return ">="
case ._lessThan: return "<"
case ._lessThanOrEqual: return "<="
case ._modulo: return "%"
case ._multiply: return "*"
case ._notEqual: return "!="
case ._subtract: return "-"
case ._and: return "AND"
case ._or: return "OR"
case ._in: return "IN"
case ._notIn: return "NOT IN"
case ._is: return "IS"
case ._isNot: return "IS NOT"
case ._like: return "LIKE"
case ._glob: return "GLOB"
case ._match: return "MATCH"
case ._regexp: return "REGEXP"
case ._notLike: return "NOT LIKE"
case ._notGlob: return "NOT GLOB"
case ._notMatch: return "NOT MATCH"
case ._notRegexp: return "NOT REGEXP"
}
}
我们可以在filter中选择适用的操作符。
Order
查询结果可以给一个order进行升序和降序排序
Todo.query(on: req).sort(\.id, .ascending).all()
Todo.query(on: req).sort(\.id, .descending).all()
Union?
目前vapor3配套的Flunt3还没有union功能,并且官方文档和源代码中并未找到union相关的方法,相信不久就会添加相关的特性,还是耐心等待,如果一旦添加了这样的方法,我会第一时间更新。
总结
vapor3的查询还是和vapor2有着比较大的差异的,之前vapor2的一个Model一统江湖的特点在vapor3上也没有得到体现,目前各个子模块也都还在开发中,希望会越来越好用吧。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1nhel12vro8mw
网友评论