There are currently two established drivers for MongoDB usable in the Swift ecosystem.
One of the libraries is the official package by MongoDB and the other is my own package called MongoKitten.
Using this pitch, I'm hoping to make a step to bringing the support for MongoDB to a higher level within the (Server-Side) Swift ecosystem.
The current situation
There are two big primary drivers that are usable, as listed above:
The first (official) one wraps around the MongoDB C library. It currently only supports synchronous requests. Aside from the synchronous implementation of executing queries, the library does not run on a NIO EventLoop.
The second library is an implementation based on SwiftNIO. It only supports asynchronous requests which has a small impact on the friendliness of the API for MongoDB's mobile database users that use the MongoKitten driver.
Proposal
The currently envisioned plan is to create two modules.
- BSON
- MongoCore
BSON is an implementation of the bson spec to read and write MongoDB's data format.
MongoCore is an objectively correct implementation of the MongoDB database protocol specification. It should handle initiating a connection, maintaining a connection and provide an API for MongoDB client libraries to send queries and receive results.
Motivation
MongoKitten is technically feature-complete, although some of the less-commonly used APIs are not implemented in a helper function.
The incentive for the MongoKitten project is to:
-
Open up to more engagement with the Swift community
-
Separate networking code from the public APIs to allow for better tests
-
Create a publically available test suite that is actively maintained and covers more edge cases
The proposed solution
There is an implementation of BSON available at OpenKitten/BSON. There is no implementation of MongoCore available, but a MongoCore + Client implementation can be found at OpenKitten/BSON.
Example APIs
let settings = try ConnectionSettings(uri: "mongodb://localhost")
// MongoCluster manages a ConnectionPool and initiates + maintains connection with all hosts
// It also runs a heartbeat and applies DNS Seedlist Discovery
// Note that MongoDB's protocol is multiplexed, so only 1 connection is made for each host
// Unlike SQL where you need many connections to the same database server
let mongoCluster = try MongoCluster.connect(with: settings).wait()
// Databases and collections are created after the first query and are a placeholder until then
// MongoKitten has a different more subjective syntax, which is slightly off this example
let database = mongoCluster.databases["app"]
let users = database.collections["users"]
struct User: Codable {
let _id: ObjectId
let name: String
}
// Reads all entities in this collection into an `Array<User>`
let users = try users.find().decode(User.self).fetchAllResults().wait()
Example implementation
I've created an example implementation in the MongoCore and MongoClient folders in the MongoKitten 6 branch: