Vapor升級到Vapor3的時間恰巧趕上WWDC砾层,本來想從美國回來就開始寫一些關(guān)于Vapor3的文章托慨,但是WWDC信息量太大了左胞,直到現(xiàn)在才轉(zhuǎn)過來寫一點關(guān)于Vapor的東西瑰抵。
這篇文章主要介紹如何使用Fluent查詢數(shù)據(jù)你雌,后面我會補(bǔ)上如何配置相關(guān)的教程。
Fluent為我們提供了一個Model類二汛, MySQLModel婿崭、 PostgreSQLModel、SQLiteModel均繼承自這個類肴颊。在Model的一個extension中氓栈,F(xiàn)lunt為我們提供了一個query方法并返回 QueryBuilder<Self.Database, Self>
下面,我們再看看這個QueryBuilder:
QueryBuilder<Self.Database, Self>
這個QueryBuilder會含有Model的類型婿着,數(shù)據(jù)庫類型授瘦,利用這些信息來連接數(shù)據(jù)庫進(jìn)行查詢幸海。
現(xiàn)在有了這個QueryBuilder了,下面就可以利用它來進(jìn)行查詢操作了:
為了簡化對問題的理解奥务,這里提供一個最簡單的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數(shù)據(jù)庫自動生成,只需要傳入一個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的數(shù)據(jù)
try Todo.query(on: req).filter(\.id ~~ [5, 7, 11]).all()
查詢id不為 5帚称、7官研、11的數(shù)據(jù)
try Todo.query(on: req).filter(\.id !~ [5, 7, 11]).all()
模糊查詢
查詢title前綴為‘work’的數(shù)據(jù)
Todo.query(on: req).filter(\.title, .like, "work%").all()
查詢title后綴為‘work’的數(shù)據(jù)
Todo.query(on: req).filter(\.title, .like, "%work").all()
查詢title包含‘work’的數(shù)據(jù)
Todo.query(on: req).filter(\.title, .like, "%work%").all()
如果只查詢一條數(shù)據(jù)
Todo.query(on: req).filter(\.title, .like, "%work%").first()
如果什么都查不出來,則會返回nil
其實模糊查詢也有提供類似于 ==, !=, >, <這樣的操作符闯睹,但是經(jīng)過測試并沒有達(dá)到比較好的效果戏羽,所以這里的demo只是展示目前我測試可用的方法,如果未來能夠支持的更好楼吃,我會再補(bǔ)充始花。
更多查詢方法:
《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
查詢結(jié)果可以給一個order進(jìn)行升序和降序排序
Todo.query(on: req).sort(\.id, .ascending).all()
Todo.query(on: req).sort(\.id, .descending).all()
Union?
目前vapor3配套的Flunt3還沒有union功能酷宵,并且官方文檔和源代碼中并未找到union相關(guān)的方法,相信不久就會添加相關(guān)的特性躬窜,還是耐心等待浇垦,如果一旦添加了這樣的方法,我會第一時間更新荣挨。
總結(jié)
vapor3的查詢還是和vapor2有著比較大的差異的男韧,之前vapor2的一個Model一統(tǒng)江湖的特點在vapor3上也沒有得到體現(xiàn),目前各個子模塊也都還在開發(fā)中默垄,希望會越來越好用吧此虑。
我的博客即將搬運(yùn)同步至騰訊云+社區(qū),邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1nhel12vro8mw