main.swift 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Foundation
  17. import FirebaseFirestore
  18. func main() {
  19. let db = initializeDb();
  20. let (collectionRef, documentRef) = makeRefs(database: db);
  21. let query = makeQuery(collection: collectionRef);
  22. writeDocument(at: documentRef);
  23. addDocument(to: collectionRef);
  24. readDocument(at: documentRef);
  25. readDocuments(matching: query);
  26. listenToDocument(at: documentRef);
  27. listenToDocuments(matching: query);
  28. types();
  29. }
  30. func initializeDb() -> Firestore {
  31. // Initialize with ProjectID.
  32. let firestore = Firestore.firestore()
  33. // Apply settings
  34. let settings = FirestoreSettings()
  35. settings.host = "localhost"
  36. settings.isPersistenceEnabled = true
  37. firestore.settings = settings
  38. return firestore;
  39. }
  40. func makeRefs(database db: Firestore) -> (CollectionReference, DocumentReference) {
  41. var collectionRef = db.collection("my-collection")
  42. var documentRef: DocumentReference;
  43. documentRef = collectionRef.document("my-doc")
  44. // or
  45. documentRef = db.document("my-collection/my-doc")
  46. // deeper collection (my-collection/my-doc/some/deep/collection)
  47. collectionRef = documentRef.collection("some/deep/collection")
  48. // parent doc (my-collection/my-doc/some/deep)
  49. documentRef = collectionRef.parent!
  50. // print paths.
  51. print("Collection: \(collectionRef.path), document: \(documentRef.path)")
  52. return (collectionRef, documentRef);
  53. }
  54. func makeQuery(collection collectionRef: CollectionReference) -> Query {
  55. let query = collectionRef.whereField(FieldPath(["name"]), isEqualTo: "Fred")
  56. .whereField("age", isGreaterThanOrEqualTo: 24)
  57. .whereField(FieldPath.documentID(), isEqualTo: "fred")
  58. .order(by: FieldPath(["age"]))
  59. .order(by: "name", descending: true)
  60. .limit(to: 10)
  61. return query;
  62. }
  63. func writeDocument(at docRef: DocumentReference) {
  64. let setData = [
  65. "foo": 42,
  66. "bar": [
  67. "baz": "Hello world!"
  68. ]
  69. ] as [String : Any];
  70. let updateData = [
  71. "bar.baz": 42,
  72. FieldPath(["foobar"]) : 42
  73. ] as [AnyHashable : Any];
  74. docRef.setData(setData)
  75. // Completion callback (via trailing closure syntax).
  76. docRef.setData(setData) { error in
  77. if let error = error {
  78. print("Uh oh! \(error)")
  79. return
  80. }
  81. print("Set complete!")
  82. }
  83. // SetOptions
  84. docRef.setData(setData, options:SetOptions.merge())
  85. docRef.updateData(updateData)
  86. docRef.delete();
  87. docRef.delete() { error in
  88. if let error = error {
  89. print("Uh oh! \(error)")
  90. return
  91. }
  92. print("Set complete!")
  93. }
  94. }
  95. func addDocument(to collectionRef: CollectionReference) {
  96. collectionRef.addDocument(data: ["foo": 42]);
  97. //or
  98. collectionRef.document().setData(["foo": 42]);
  99. }
  100. func readDocument(at docRef: DocumentReference) {
  101. // Trailing closure syntax.
  102. docRef.getDocument() { document, error in
  103. if let document = document {
  104. // NOTE that document is nullable.
  105. let data = document.data();
  106. print("Read document: \(data)")
  107. // Fields are read via subscript notation.
  108. if let foo = document["foo"] {
  109. print("Field: \(foo)")
  110. }
  111. } else {
  112. // TODO(mikelehen): There may be a better way to do this, but it at least demonstrates
  113. // the swift error domain / enum codes are renamed appropriately.
  114. if let errorCode = error.flatMap({
  115. ($0._domain == FirestoreErrorDomain) ? FirestoreErrorCode (rawValue: $0._code) : nil
  116. }) {
  117. switch errorCode {
  118. case .unavailable:
  119. print("Can't read document due to being offline!")
  120. case _:
  121. print("Failed to read.")
  122. }
  123. } else {
  124. print("Unknown error!")
  125. }
  126. }
  127. }
  128. }
  129. func readDocuments(matching query: Query) {
  130. query.getDocuments() { querySnapshot, error in
  131. // TODO(mikelehen): Figure out how to make "for..in" syntax work
  132. // directly on documentSet.
  133. for document in querySnapshot!.documents {
  134. print(document.data())
  135. }
  136. }
  137. }
  138. func listenToDocument(at docRef: DocumentReference) {
  139. let listener = docRef.addSnapshotListener() { document, error in
  140. if let error = error {
  141. print("Uh oh! Listen canceled: \(error)")
  142. return
  143. }
  144. if let document = document {
  145. print("Current document: \(document.data())");
  146. if (document.metadata.isFromCache) {
  147. print("From Cache")
  148. } else {
  149. print("From Server")
  150. }
  151. }
  152. }
  153. // Unsubscribe.
  154. listener.remove();
  155. }
  156. func listenToDocuments(matching query: Query) {
  157. let listener = query.addSnapshotListener() { snap, error in
  158. if let error = error {
  159. print("Uh oh! Listen canceled: \(error)")
  160. return
  161. }
  162. if let snap = snap {
  163. print("NEW SNAPSHOT (empty=\(snap.isEmpty) count=\(snap.count)")
  164. // TODO(mikelehen): Figure out how to make "for..in" syntax work
  165. // directly on documentSet.
  166. for document in snap.documents {
  167. print("Doc: ", document.data())
  168. }
  169. }
  170. }
  171. // Unsubscribe
  172. listener.remove();
  173. }
  174. func listenToQueryDiffs(onQuery query: Query) {
  175. let listener = query.addSnapshotListener() { snap, error in
  176. if let snap = snap {
  177. for change in snap.documentChanges {
  178. switch (change.type) {
  179. case .added:
  180. print("New document: \(change.document.data())")
  181. case .modified:
  182. print("Modified document: \(change.document.data())")
  183. case .removed:
  184. print("Removed document: \(change.document.data())")
  185. }
  186. }
  187. }
  188. }
  189. // Unsubscribe
  190. listener.remove();
  191. }
  192. func transactions() {
  193. let db = Firestore.firestore()
  194. let collectionRef = db.collection("cities")
  195. let accA = collectionRef.document("accountA")
  196. let accB = collectionRef.document("accountB")
  197. let amount = 20.0
  198. db.runTransaction({ (transaction, errorPointer) -> Any? in
  199. do {
  200. let balanceA = try transaction.getDocument(accA)["balance"] as! Double
  201. let balanceB = try transaction.getDocument(accB)["balance"] as! Double
  202. if (balanceA < amount) {
  203. errorPointer?.pointee = NSError(domain: "Foo", code: 123, userInfo: nil)
  204. return nil
  205. }
  206. transaction.updateData(["balance": balanceA - amount], forDocument:accA)
  207. transaction.updateData(["balance": balanceB + amount], forDocument:accB)
  208. } catch let error as NSError {
  209. print("Uh oh! \(error)")
  210. }
  211. return 0
  212. }) { (result, error) in
  213. // handle result.
  214. }
  215. }
  216. func types() {
  217. let _: CollectionReference;
  218. let _: DocumentChange;
  219. let _: DocumentListenOptions;
  220. let _: DocumentReference;
  221. let _: DocumentSnapshot;
  222. let _: FieldPath;
  223. let _: FieldValue;
  224. let _: Firestore;
  225. let _: FirestoreSettings;
  226. let _: GeoPoint;
  227. let _: ListenerRegistration;
  228. let _: QueryListenOptions;
  229. let _: Query;
  230. let _: QuerySnapshot;
  231. let _: SetOptions;
  232. let _: SnapshotMetadata;
  233. let _: Transaction;
  234. let _: WriteBatch;
  235. }