From e60640e1c7ee11b87b0eba9490310bfdca18f693 Mon Sep 17 00:00:00 2001 From: Joannis Orlandos Date: Wed, 3 Jan 2018 00:18:58 +0100 Subject: [PATCH] More MongoDB basics --- 3.0/docs/databases/mongodb/basics.md | 76 ++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/3.0/docs/databases/mongodb/basics.md b/3.0/docs/databases/mongodb/basics.md index 201e236a..76e6a046 100644 --- a/3.0/docs/databases/mongodb/basics.md +++ b/3.0/docs/databases/mongodb/basics.md @@ -55,6 +55,11 @@ struct User: Codable { var _id = ObjectId() var username: String var age: Int + + init(named name: String, age: Int) { + self.username = named + self.age = age + } } let users = database["users"].map(to: User.self) @@ -96,6 +101,7 @@ There is also `findOne`, which is useful when you want to exactly one object. Th The filter is a MongoKitten [`Query`](query.md) object. ```swift +// User? guard let joannis = users.findOne("username" == "Joannis" && "active" == true) else { return } @@ -107,9 +113,10 @@ A range is any native swift Range. It is used for `skip` and `limit`. ```swift // Cursor with the first 10 users -let users1 = users.find(in: ..<10) -let users2 = users.find(in: 10..<20) -let users3 = users.find(in: 30...) + +let users1 = users.find(in: ..<10) // Cursor +let users2 = users.find(in: 10..<20) // Cursor +let users3 = users.find(in: 30...) // Cursor ``` ### Sort @@ -117,7 +124,7 @@ let users3 = users.find(in: 30...) The [`Sort`](sort.md) is used to sort entities in either ascending or descending order based on one or more fields. ```swift -let maleUsers = users.find("gender" == "male", sortedBy: ["age": .ascending]) +let maleUsers = users.find("gender" == "male", sortedBy: ["age": .ascending]) // Cursor ``` ### Projection @@ -125,7 +132,66 @@ let maleUsers = users.find("gender" == "male", sortedBy: ["age": .ascending]) The [projection](projection.md) ensures only the specifies subset of fields are returned. Projections can also be computed fields. Remember that the projection must fit within the Collection's Codable type. If this is not a dictionary(-like) type such as `Document` it will be required that the Document fetched matches the Codable type. ```swift -let adults = users.find("age" >= 21, projecting: ["_id": .excluded, "username": .included]) +let adults = users.find("age" >= 21, projecting: ["_id": .excluded, "username": .included]) // Cursor +``` + +## Count + +Count is similar to a find operation in that it is a read-only operation. Since it does not return the actual data (only an integer of the total entities found) it does not support projections and sorting. It does support a range expression, although it's not often used. + +```swift +let totalUsers = users.count() // Future +let femaleUsers = users.count("gender" == "female") // Future +``` + +## Update + +Updating can be done on one or all entities. Updates can either update the entire entity or only a subset of fields. + +```swift +let user = User(named: "Joannis", age: 111) + +users.update("username" == "Joannis", to: user) +``` + +Update also indicates a success state in the same way `insert` does. + +### Updating fields + +Updating a subset of fields can be done more efficiently using + +```swift +// Rename `Joannis` -> `JoannisO` +users.update("username" == "Joannis", fields: [ + "username": "JoannisO" +]) + +// Migrate all users to require a password update +users.update(fields: [ + "resetPassword": true +]) +``` + +### Upsert + +If you don't know if an entity exists but want it inserted/updated accordingly you should use `upsert`. + +```swift +let user = User(named: "Joannis", age: 111) + +users.upsert("_id" == user._id, to: user) +``` + +## Remove + +Remove removes the first or all entities matching a query. + +```swift +// Remove me! +users.remove("username" == "Joannis") + +// Remove all Dutch users +users.removeAll("country" == "NL") ``` # Troubleshooting