| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- import Foundation
- import FirebaseFirestore
- func main() {
- let db = initializeDb();
- let (collectionRef, documentRef) = makeRefs(database: db);
- let query = makeQuery(collection: collectionRef);
- writeDocument(at: documentRef);
- addDocument(to: collectionRef);
- readDocument(at: documentRef);
- readDocuments(matching: query);
- listenToDocument(at: documentRef);
- listenToDocuments(matching: query);
- types();
- }
- func initializeDb() -> Firestore {
- // Initialize with ProjectID.
- let firestore = Firestore.firestore()
- // Apply settings
- let settings = FirestoreSettings()
- settings.host = "localhost"
- settings.isPersistenceEnabled = true
- firestore.settings = settings
- return firestore;
- }
- func makeRefs(database db: Firestore) -> (CollectionReference, DocumentReference) {
- var collectionRef = db.collection("my-collection")
- var documentRef: DocumentReference;
- documentRef = collectionRef.document("my-doc")
- // or
- documentRef = db.document("my-collection/my-doc")
- // deeper collection (my-collection/my-doc/some/deep/collection)
- collectionRef = documentRef.collection("some/deep/collection")
- // parent doc (my-collection/my-doc/some/deep)
- documentRef = collectionRef.parent!
- // print paths.
- print("Collection: \(collectionRef.path), document: \(documentRef.path)")
- return (collectionRef, documentRef);
- }
- func makeQuery(collection collectionRef: CollectionReference) -> Query {
- let query = collectionRef.whereField(FieldPath(["name"]), isEqualTo: "Fred")
- .whereField("age", isGreaterThanOrEqualTo: 24)
- .whereField(FieldPath.documentID(), isEqualTo: "fred")
- .order(by: FieldPath(["age"]))
- .order(by: "name", descending: true)
- .limit(to: 10)
- return query;
- }
- func writeDocument(at docRef: DocumentReference) {
- let setData = [
- "foo": 42,
- "bar": [
- "baz": "Hello world!"
- ]
- ] as [String : Any];
- let updateData = [
- "bar.baz": 42,
- FieldPath(["foobar"]) : 42
- ] as [AnyHashable : Any];
- docRef.setData(setData)
- // Completion callback (via trailing closure syntax).
- docRef.setData(setData) { error in
- if let error = error {
- print("Uh oh! \(error)")
- return
- }
- print("Set complete!")
- }
- // SetOptions
- docRef.setData(setData, options:SetOptions.merge())
- docRef.updateData(updateData)
- docRef.delete();
- docRef.delete() { error in
- if let error = error {
- print("Uh oh! \(error)")
- return
- }
- print("Set complete!")
- }
- }
- func addDocument(to collectionRef: CollectionReference) {
- collectionRef.addDocument(data: ["foo": 42]);
- //or
- collectionRef.document().setData(["foo": 42]);
- }
- func readDocument(at docRef: DocumentReference) {
- // Trailing closure syntax.
- docRef.getDocument() { document, error in
- if let document = document {
- // NOTE that document is nullable.
- let data = document.data();
- print("Read document: \(data)")
- // Fields are read via subscript notation.
- if let foo = document["foo"] {
- print("Field: \(foo)")
- }
- } else {
- // TODO(mikelehen): There may be a better way to do this, but it at least demonstrates
- // the swift error domain / enum codes are renamed appropriately.
- if let errorCode = error.flatMap({
- ($0._domain == FirestoreErrorDomain) ? FirestoreErrorCode (rawValue: $0._code) : nil
- }) {
- switch errorCode {
- case .unavailable:
- print("Can't read document due to being offline!")
- case _:
- print("Failed to read.")
- }
- } else {
- print("Unknown error!")
- }
- }
- }
- }
- func readDocuments(matching query: Query) {
- query.getDocuments() { querySnapshot, error in
- // TODO(mikelehen): Figure out how to make "for..in" syntax work
- // directly on documentSet.
- for document in querySnapshot!.documents {
- print(document.data())
- }
- }
- }
- func listenToDocument(at docRef: DocumentReference) {
- let listener = docRef.addSnapshotListener() { document, error in
- if let error = error {
- print("Uh oh! Listen canceled: \(error)")
- return
- }
- if let document = document {
- print("Current document: \(document.data())");
- if (document.metadata.isFromCache) {
- print("From Cache")
- } else {
- print("From Server")
- }
- }
- }
- // Unsubscribe.
- listener.remove();
- }
- func listenToDocuments(matching query: Query) {
- let listener = query.addSnapshotListener() { snap, error in
- if let error = error {
- print("Uh oh! Listen canceled: \(error)")
- return
- }
- if let snap = snap {
- print("NEW SNAPSHOT (empty=\(snap.isEmpty) count=\(snap.count)")
- // TODO(mikelehen): Figure out how to make "for..in" syntax work
- // directly on documentSet.
- for document in snap.documents {
- print("Doc: ", document.data())
- }
- }
- }
- // Unsubscribe
- listener.remove();
- }
- func listenToQueryDiffs(onQuery query: Query) {
- let listener = query.addSnapshotListener() { snap, error in
- if let snap = snap {
- for change in snap.documentChanges {
- switch (change.type) {
- case .added:
- print("New document: \(change.document.data())")
- case .modified:
- print("Modified document: \(change.document.data())")
- case .removed:
- print("Removed document: \(change.document.data())")
- }
- }
- }
- }
- // Unsubscribe
- listener.remove();
- }
- func transactions() {
- let db = Firestore.firestore()
- let collectionRef = db.collection("cities")
- let accA = collectionRef.document("accountA")
- let accB = collectionRef.document("accountB")
- let amount = 20.0
- db.runTransaction({ (transaction, errorPointer) -> Any? in
- do {
- let balanceA = try transaction.getDocument(accA)["balance"] as! Double
- let balanceB = try transaction.getDocument(accB)["balance"] as! Double
- if (balanceA < amount) {
- errorPointer?.pointee = NSError(domain: "Foo", code: 123, userInfo: nil)
- return nil
- }
- transaction.updateData(["balance": balanceA - amount], forDocument:accA)
- transaction.updateData(["balance": balanceB + amount], forDocument:accB)
- } catch let error as NSError {
- print("Uh oh! \(error)")
- }
- return 0
- }) { (result, error) in
- // handle result.
- }
- }
- func types() {
- let _: CollectionReference;
- let _: DocumentChange;
- let _: DocumentListenOptions;
- let _: DocumentReference;
- let _: DocumentSnapshot;
- let _: FieldPath;
- let _: FieldValue;
- let _: Firestore;
- let _: FirestoreSettings;
- let _: GeoPoint;
- let _: ListenerRegistration;
- let _: QueryListenOptions;
- let _: Query;
- let _: QuerySnapshot;
- let _: SetOptions;
- let _: SnapshotMetadata;
- let _: Transaction;
- let _: WriteBatch;
- }
|