Vapor 2.0 - 查詢(Query)

前往 Vapor 2.0 - 文檔目錄

Fluent的查詢構(gòu)建器提供了一個創(chuàng)建復(fù)雜數(shù)據(jù)庫查詢的簡單界面。在Query類本身(不包含原始查詢)是通過Fluent的與數(shù)據(jù)庫通信的唯一方法。

構(gòu)造(Make)

您可以從任何模型類創(chuàng)建一個新的查詢構(gòu)建器。

let query = try Post.makeQuery()

您還可以從實例創(chuàng)建查詢。如果您需要使用特殊的數(shù)據(jù)庫連接(如事務(wù)處理(transactions))來保存或更新模型,這一點尤其有用。

guard let post = try Post.find(42) else { ... }
post.content = "Updated"
let query = try post.makeQuery(conn).save()

獲取(Fetch)

您有多個選項用于獲取查詢的結(jié)果。

全部(All)

最簡單的選項.all()返回與查詢相關(guān)的所有行。

let users = try User.makeQuery().filter(...).all()

首先(First)

你也可以用.first()只獲取第一行。

let user = try User.makeQuery().filter(...).first()

Fluent會自動將結(jié)果限制為1,以提高查詢的性能。

數(shù)據(jù)塊(Chunk)

如果要從數(shù)據(jù)庫中獲取大量的模型,則使用.chunk()可以幫助通過一次獲取數(shù)據(jù)塊來減少查詢所需的內(nèi)存量。

User.makeQuery().filter(...).chunk(32) { users in
    print(users)
}

過濾器(Filter)

過濾器允許您選擇想要修改或獲取的數(shù)據(jù)子集。有三種不同類型的過濾器。

比較(Compare)

比較過濾器在數(shù)據(jù)庫中的模型和提供的值之間進(jìn)行比較。

try query.filter("age", .greaterThanOrEquals, 21)

你也可以使用運(yùn)算符。

try query.filter("age" >= 21)
案例Case 運(yùn)算符Operator 類型Type
.equals == Equals
.greaterThan > Greater Than
.lessThan < Less Than
.greaterThanOrEquals >= Greater Than Or Equals
.lessThanOrEquals <= Less Than Or Equals
.notEquals != Not Equals
.hasSuffix Has Suffix
.hasPrefix Has Prefix
.contains Contains
.custom(String) Custom

提示
您可以省略比較類型.equals,例如,query.filter("age", 23)

子集(Subset)

您還可以根據(jù)一組數(shù)據(jù)中的字段進(jìn)行篩選。

try query.filter("favoriteColor", in: ["pink", "blue"])

或者相反。

try query.filter("favoriteColor", notIn: ["brown", "black"])

組(Group)

默認(rèn)情況下,所有的查詢過濾器都是與(AND)邏輯連接的。您可以在您的查詢中創(chuàng)建一組過濾器,這些過濾器是與(AND)或或(OR)邏輯一起連接的。

try query.or { orGroup in
    try orGroup.filter("age", .greaterThan, 75)
    try orGroup.filter("age", .lessThan, 18)
}

這將導(dǎo)致SQL類似于以下內(nèi)容:

SELECT * FROM `users` WHERE (`age` > 75 OR `age` < 18);

.and()也是可用的,以防您需要用嵌套了一個或(OR)的與(AND)來切換回連接過濾器。

復(fù)雜示例(Complex Example)
let users = try User
    .makeQuery()
    .filter("planetOfOrigin", .greaterThan, "Earth")
    .or { orGroup in
        orGroup.and { andGroup in
            andGroup.filter("name", "Rick")
            andGroup.filter("favoriteFood", "Beer")
        }
        orGroup.and { andGroup in
            andGroup.filter("name", "Morty")
            andGroup.filter("favoriteFood", "Eyeholes")
        }
    }
    .all()

這將導(dǎo)致SQL類似于以下內(nèi)容:

SELECT * FROM `users`
    WHERE `planetOfOrigin` = 'Earth' AND (
           (`name` = 'Rick' AND `favoriteFood` = 'Beer')
        OR (`name` = 'Morty' AND `favoriteFood` = 'Eyeholes')
    )

注意
請記住,組的AND / OR邏輯僅適用于組內(nèi)添加的過濾器。過濾器組外的所有過濾器將由AND連接。

原始(Raw)

原始過濾器可用于通過不應(yīng)參數(shù)化的值進(jìn)行過濾。

try query.filter(raw: "date >= CURRENT_TIMESTAMP")

不同(Distinct)

要僅從數(shù)據(jù)庫中選擇不同的模型,請?zhí)砑?code>.distinct()到您的查詢中。

try query.distinct()

限制/偏移(Limit / Offset)

要限制或偏移查詢,請使用該.limit()方法。

try query.limit(20, offset: 5)

排序(Sort)

要對查詢的結(jié)果進(jìn)行排序,請使用該.sort()方法。

try query.sort("age", .descending)

您可以通過鏈接您的.sort()調(diào)用一次對多個列進(jìn)行排序。

try query.sort("age", .descending).sort("shoe_size")

加入(Join)

您可以將兩個模型表連接在一起,如果要通過另一個模型的屬性過濾一個模型,這將非常有用。例如,假設(shè)你有一個屬于Departments的Employees表。你想知道哪個部門包含已經(jīng)完成了十年服務(wù)的員工。

首先,使用.join()部門查詢中的方法將其與Employee表一起加入。接下來你鏈接.filter()到查詢。請記住,您需要將“已連接”模型顯式傳遞給過濾器,否則Fluent將嘗試在“基本”模型上過濾。

let departments = try Department.makeQuery()
  .join(Employee.self)
  .filter(Employee.self, "years_of_service" >= 10)

Fluent將為您提供關(guān)系領(lǐng)域,但您也可以使用baseKeyjoinedKey方法參數(shù)指定它們,baseKey“base”模型(Department)上的標(biāo)識符字段在哪里,并且joinedKey是“加入”模型的外鍵字段(員工)涉及“基地”模式。

提示
Fluent支持內(nèi)部和外部連接; 使用調(diào)用.join(kind: .outer, MyModel.self)

原始(Raw)

如果您需要執(zhí)行查詢構(gòu)建器不支持的查詢,則可以使用原始查詢。

try drop.database?.raw("SELECT @@version")

您也可以使用給定模型的數(shù)據(jù)庫。

User.database?.raw("SELECT * FROM `users`")

除了為查詢數(shù)據(jù)庫提供了一個更具表達(dá)性的接口外,查詢構(gòu)建器還采取了一些措施,通過自動清除輸入來增加安全性。因此,可以嘗試使用查詢類來執(zhí)行原始查詢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容