More MongoDB basics

This commit is contained in:
Joannis Orlandos 2018-01-03 00:18:58 +01:00
parent 5f11dcac7f
commit e60640e1c7
1 changed files with 71 additions and 5 deletions

View File

@ -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<User>
let users2 = users.find(in: 10..<20) // Cursor<User>
let users3 = users.find(in: 30...) // Cursor<User>
```
### 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<User>
```
### 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<User>
```
## 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<Int>
let femaleUsers = users.count("gender" == "female") // Future<Int>
```
## 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