开发暂停

我们在此宣布我们停止开发 MongoDB 服务器端 Swift 驱动程序的决定。该项目将不再提供进一步的开发、错误修复、增强功能、文档更改或维护,并且不再接受 pull request。

仍然有方法可以将 MongoDB 与 Swift 结合使用

欢迎社区成员和开发人员 fork 我们现有的驱动程序并根据您的需要添加功能 - Swift 驱动程序采用 Apache 2.0 许可证,源代码可在 GitHub 上找到。对于开发客户端/移动应用程序的开发者,MongoDB 提供了 Realm Swift SDK,可与 MongoDB Atlas 进行实时同步。

我们想借此机会衷心感谢 Swift 社区对 MongoDB 的热情支持。在我们的旅程中,您的忠诚和反馈对我们来说非常宝贵,我们希望将来能够恢复服务器端 Swift 驱动程序的开发。

sswg:incubating|104x20

MongoSwift

适用于 macOS 和 Linux 上 Swift 应用程序的官方 MongoDB 驱动程序。

索引

文档

驱动程序的最新文档可在此处 获取。驱动程序的 BSON 库的最新文档可在此处 获取

错误 / 功能请求

认为您找到了错误?想要在 mongo-swift-driver 中看到新功能?请在我们的问题管理工具 JIRA 中提交一个案例

  1. 创建一个帐户并登录:jira.mongodb.org
  2. 导航到 SWIFT 项目:jira.mongodb.org/browse/SWIFT
  3. 点击 创建 Issue - 请尽可能提供关于问题以及如何重现它的信息。

JIRA 中所有驱动程序项目(即 NODE、PYTHON、CSHARP、JAVA)和核心服务器(即 SERVER)项目的错误报告都是公开的

安全问题

有关我们安全流程的详细信息,请参阅 SECURITY.md

安装

该驱动程序支持与 Swift 5.1+ 一起使用。构建驱动程序所需的最低 macOS 版本为 10.14。该驱动程序在持续集成中针对 macOS 11 和 12 以及 Ubuntu 18.04 和 20.04 进行了测试。

通过 Swift Package Manager 支持安装。

您可以在此仓库的 发布页面 中找到有关我们所有版本的详细信息。

步骤 1:安装所需的系统库(仅限 Linux)

该驱动程序供应商和包装了 MongoDB C 驱动程序 (libmongoc),它在 Linux 环境中构建时依赖于许多外部 C 库。因此,必须在您的系统上安装这些库才能构建 MongoSwift。

要安装这些库,请按照 libmongoc 文档中的 说明 进行操作。

步骤 2:安装驱动程序

该驱动程序包含两个模块以支持各种用例:MongoSwift 中的异步 API 和 MongoSwiftSync 中的同步 API。这些模块共享许多核心类型,例如选项 struct。该驱动程序依赖于我们的库 swift-bson,其中包含 BSON 实现。所有 BSON 符号都从驱动程序模块重新导出,因此您无需在应用程序中显式 import BSON

要安装驱动程序,请将软件包和相关模块作为依赖项添加到项目的 Package.swift 文件中

// swift-tools-version:5.1
import PackageDescription

let package = Package(
    name: "MyPackage",
    platforms: [
        .macOS(.v10_14) // minimum macOS version driver supports
    ],
    dependencies: [
        .package(url: "https://github.com/mongodb/mongo-swift-driver", .upToNextMajor(from: "1.3.1"))
    ],
    targets: [
        // Async module
        .target(name: "MyAsyncTarget", dependencies: ["MongoSwift"]),
        // Sync module
        .target(name: "MySyncTarget", dependencies: ["MongoSwiftSync"])
    ]
)

然后运行 swift build 来下载、编译和链接所有依赖项。

示例用法

注意:您应该在应用程序结束时精确调用一次 cleanupMongoSwift(),以释放 libmongoc 分配的所有内存和其他资源。

连接到 MongoDB 并创建集合

Async/Await(推荐):

import MongoSwift
import NIOPosix

let elg = MultiThreadedEventLoopGroup(numberOfThreads: 4)
let client = try MongoClient("mongodb://:27017", using: elg)

defer {
    // clean up driver resources
    try? client.syncClose()
    cleanupMongoSwift()

    // shut down EventLoopGroup
    try? elg.syncShutdownGracefully()
}

let db = client.db("myDB")
let collection = try await db.createCollection("myCollection")
// use collection...

异步 (EventLoopFutures):

import MongoSwift
import NIOPosix

let elg = MultiThreadedEventLoopGroup(numberOfThreads: 4)
let client = try MongoClient("mongodb://:27017", using: elg)

defer {
    // clean up driver resources
    try? client.syncClose()
    cleanupMongoSwift()

    // shut down EventLoopGroup
    try? elg.syncShutdownGracefully()
}

let db = client.db("myDB")

let result = db.createCollection("myCollection").flatMap { collection in
    // use collection...
}

同步:

import MongoSwiftSync

defer {
    // free driver resources
    cleanupMongoSwift()
}

let client = try MongoClient("mongodb://:27017")

let db = client.db("myDB")
let collection = try db.createCollection("myCollection")

// use collection...

注意:为了清晰起见,我们包含了客户端 connectionString 参数,但如果连接到默认的 "mongodb://:27017",则可以省略它。

创建并插入文档

Async/Await(推荐):

let doc: BSONDocument = ["_id": 100, "a": 1, "b": 2, "c": 3]
let result = try await collection.insertOne(doc)
print(result?.insertedID ?? "") // prints `.int64(100)`

异步 (EventLoopFutures):

let doc: BSONDocument = ["_id": 100, "a": 1, "b": 2, "c": 3]
collection.insertOne(doc).whenSuccess { result in
    print(result?.insertedID ?? "") // prints `.int64(100)`
}

同步:

let doc: BSONDocument = ["_id": 100, "a": 1, "b": 2, "c": 3]
let result = try collection.insertOne(doc)
print(result?.insertedID ?? "") // prints `.int64(100)`

查找文档

Async/Await(推荐):

let query: BSONDocument = ["a": 1]
// The `sort` option specifies the order in which results are returned
// via the cursor. In this case, `["_id": -1]` indicates that the documents will
// be returned in descending order according to the `_id` field.
let options = FindOptions(sort: ["_id": -1])
for try await doc in try await collection.find(query, options: options) {
    print(doc)
}

异步 (EventLoopFutures):

let query: BSONDocument = ["a": 1]
// The `sort` option specifies the order in which results are returned
// via the cursor. In this case, `["_id": -1]` indicates that the documents will
// be returned in descending order according to the `_id` field.
let options = FindOptions(sort: ["_id": -1])
let result = collection.find(query, options: options).flatMap { cursor in
    cursor.forEach { doc in
        print(doc)
    }
}

同步:

let query: BSONDocument = ["a": 1]
// The `sort` option specifies the order in which results are returned
// via the cursor. In this case, `["_id": -1]` indicates that the documents will
// be returned in descending order according to the `_id` field.
let options = FindOptions(sort: ["_id": -1])
let documents = try collection.find(query, options: options)
for d in documents {
    print(try d.get())
}

处理和修改文档

var doc: BSONDocument = ["a": 1, "b": 2, "c": 3]

print(doc) // prints `{"a" : 1, "b" : 2, "c" : 3}`
print(doc["a"] ?? "") // prints `.int64(1)`

// Set a new value
doc["d"] = 4
print(doc) // prints `{"a" : 1, "b" : 2, "c" : 3, "d" : 4}`

// Using functional methods like map, filter:
let evensDoc = doc.filter { elem in
    guard let value = elem.value.asInt() else {
        return false
    }
    return value % 2 == 0
}
print(evensDoc) // prints `{ "b" : 2, "d" : 4 }`

let doubled = doc.map { elem -> Int in
    guard case let value = .int64(value) else {
        return 0
    }

    return Int(value * 2)
}
print(doubled) // prints `[2, 4, 6, 8]`

请注意,BSONDocument 符合 Collection,因此来自 SequenceCollection 的有用方法都可用。但是,许多这些方法的运行时保证尚未满足。

与 Kitura、Vapor 和 Perfect 一起使用

Examples/ 目录包含使用驱动程序与 KituraVaporPerfect 的示例 Web 应用程序项目。我们还有一个示例 全栈 Swift 应用程序,它具有 iOS 前端和使用 Vapor 构建的后端。

请注意,该驱动程序是使用 SwiftNIO 2 构建的,因此与基于 SwiftNIO 1 构建的框架不兼容。Vapor 4.0 和 Kitura 2.5 及更高版本使用 SwiftNIO 2。

开发说明

有关构建和测试驱动程序的说明,请参阅我们的 开发指南