You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`Cloud Firestore` jest elastyczną, skalowalną, hierarchiczną bazą danych `NoSQL` w chmurze służącą do przechowywania i synchronizowania w czasie rzeczywistym danych między klientami i serwerem. Oferuje wsparcie w trybie `offline` co ułatwia budowania responsywnych aplikacji działających niezależnie od jakości połączenia sieciowego. Umożliwia integracje z `Google Cloud Platform` i funkcjonalnościami `Firebase` jak np. `Cloud Functions` czy `Authentication` oraz innymi zewnętrznymi usługami. Dostęp i modyfikacja danych odbywa się zgodnie z zasadami zachowania bezpieczeństwa i prywatności, które mogą być dodatkowo definiowane za pomocą reguł w konsoli Firebase.
15
15
16
16
## Model
17
-
Dane reprezentowane są w postaci dokumentów (zbliżonych w stukurze do formatu `JSON`) przechowywanych w zorganizowanej kolekcji w hierarchicznej strukturze bazy danych `NoSQL` (w przeciwieństwie do `SQL` nie ma tabel ani wierszy). Każdy `dokument` składa się z nazwy, zbioru par `klucz - wartość` (prymityw lub obiekt złożony) i może posiadać obiekty zagnieżdzone i podkolekcje. `Kolekcje` pełnią rolę kontenera dla różnych dokumentów i nie mogą posiadać innych kolekcji, a w doborze ich zawartości warto zachować logiczny porządek dzieląc dokumenty ze względu na kategorie i przeznaczenie co upraszcza poruszanie się po strukturze w kodzie klienta. `Podkolekcja` jest kolekcją w dokumencie i służy do budowania zagnieżdzonej struktury folderów.
17
+
Dane reprezentowane są w postaci dokumentów (zbliżonych w stukurze do formatu `JSON`) przechowywanych w zorganizowanej kolekcji w hierarchicznej strukturze bazy danych `NoSQL` (w przeciwieństwie do `SQL` nie ma tabel ani wierszy). Każdy `dokument`(`document`) składa się z nazwy, zbioru par `klucz - wartość` (prymityw lub obiekt złożony) i może posiadać obiekty zagnieżdzone i podkolekcje. `Kolekcje`(`collection`) pełnią rolę kontenera dla różnych dokumentów i nie mogą posiadać innych kolekcji, a w doborze ich zawartości warto zachować logiczny porządek dzieląc dokumenty ze względu na kategorie i przeznaczenie co upraszcza poruszanie się po strukturze w kodzie klienta. `Podkolekcja` jest kolekcją w dokumencie i służy do budowania zagnieżdzonej struktury folderów.
18
18
19
19
//TODO rysunek
20
20
21
-
Ze względu na optymalizacje wydajności dostępu do bazy danych wprowadzony został mechanizm indeksowania, który wyróżnia dwa rodzaje indeksów: `single-field` (przechowuje posortowaną mapę wszystkich dokumentów zawierających dane pole) i `composite` (przechowuje posortowaną mapę wszystkich dokumentów zawierających wiele danych pól). Cloud Firestore jest zaprojektowany przede wszystkim z myślą o dużych kolekcjach małych dokumentów. Aby uzyskać dostęp do dokumentu lub kolekcji należy uzyskać `referencje`.
21
+
Ze względu na optymalizacje wydajności dostępu do bazy danych wprowadzony został mechanizm indeksowania, który wyróżnia dwa rodzaje indeksów: `single-field` (przechowuje posortowaną mapę wszystkich dokumentów zawierających dane pole) i `composite` (przechowuje posortowaną mapę wszystkich dokumentów zawierających wiele danych pól). Cloud Firestore jest zaprojektowany przede wszystkim z myślą o dużych kolekcjach małych dokumentów. Aby uzyskać dostęp do dokumentu lub kolekcji należy uzyskać `referencje` - obiekt typu `DocumentReference`.
22
22
23
23
{% highlight kotlin %}
24
24
private fun createReferences() {
25
-
val database = FirebaseFirestore.getInstance()
26
-
val collectionRef = database.collection("collection")
27
-
val documentRef = collectionRef.document("document")
28
-
val documentRef2 = database.document("collection/document") //or use direct path instead
29
-
val nestedDocumentRef = documentRef.collection("subcollection").document("nested")
25
+
val database = FirebaseFirestore.getInstance()
26
+
val collectionRef = database.collection("collection")
27
+
val documentRef = collectionRef.document("document")
28
+
val documentRef2 = database.document("collection/document") //or use direct path instead
29
+
val nestedDocumentRef = documentRef.collection("subcollection").document("nested")
30
30
}
31
31
{% endhighlight %}
32
32
@@ -35,39 +35,210 @@ Dokumenty mogą przechowywać wartości `prymitywów` (numeryczne, logiczne, tek
35
35
36
36
{% highlight kotlin %}
37
37
private fun createExampleData() {
38
-
val document = HashMap<String, Any?>()
39
-
document["text"] = "value"
40
-
document["logic"] = true
41
-
document["number"] = 9.99
42
-
document["date"] = Timestamp(Date())
43
-
document["list"] = arrayListOf(1,2,3)
44
-
document["null"] = null
38
+
val document = HashMap<String, Any?>()
39
+
document["text"] = "value"
40
+
document["logic"] = true
41
+
document["number"] = 9.99
42
+
document["date"] = Timestamp(Date())
43
+
document["list"] = arrayListOf(1,2,3)
44
+
document["null"] = null
45
45
}
46
46
47
47
private fun createSimilarData() {
48
-
val person = HashMap<String, Any>()
49
-
person["name"] = "John"
50
-
person["surname"] = "Walker"
51
-
person["born"] = 1805
48
+
val person = HashMap<String, Any>()
49
+
person["name"] = "John"
50
+
person["surname"] = "Walker"
51
+
person["born"] = 1805
52
52
53
-
//structure of data in the same collection don't have to be exactly the same
54
-
val person2 = HashMap<String, Any>()
55
-
person["name"] = "Jasper"
56
-
person["second"] = "Newton"
57
-
person["surname"] = "Daniel"
58
-
person["born"] = 1850
53
+
//structure of data in the same collection don't have to be exactly the same
54
+
val person2 = HashMap<String, Any>()
55
+
person2["name"] = "Jasper"
56
+
person2["second"] = "Newton"
57
+
person2["surname"] = "Daniel"
58
+
person2["born"] = 1850
59
59
60
-
//add to database by passing those objects
60
+
//add to database by passing those objects
61
61
}
62
62
63
63
private fun createDataByObject() {
64
-
val person = Person("William", "Grant", 1839)
65
-
//add to database by passing object
64
+
val person = Person("William", "Grant", 1839)
65
+
//add to database by passing object
66
66
}
67
67
{% endhighlight %}
68
68
69
-
## Operacje
70
-
//TODO
69
+
## Zapis
70
+
Aby dokonać zapisu w Cloud Firestore należy podać identyfikator dokumentu oraz przekazać obiekt danych metodą `set` lub w przypadku automatycznego generowania id wystarczy tylko przekazać danę metodą `add`. Jeśli dokument nie istnieje wówczas zostanie utworzy, w przeciwnym razie jego zawartośc zostanie nadpisana, chyba że zostaną użyte odpowiednie opcje. Dodanie obserwatorów umożliwia śledzenie stanu operacji.
//or use reference.set(club, SetOptions.merge()) for merge if file exists
89
+
}
90
+
91
+
private fun addDataWithoutId() {
92
+
var club = Club("Chelsea FC", "England", 1905)
93
+
database.collection("club").add(club)
94
+
.addOnSuccessListener {
95
+
//some action
96
+
}
97
+
.addOnFailureListener {
98
+
//some action
99
+
}
100
+
}
101
+
{% endhighlight %}
102
+
103
+
W celu aktualizacji wybranych pól dokumentu bez nadpisywania całej jego zawartości należy użyć metodę `update` na referencji. Odwołując się do obiektów zagnieżdzonych należy wykorzystać właściwą notację oddzielając pola i wartości przecinkiem, a w przypadku modyfikacji elementów tablic użyć metod `FieldValue.arrayUnion` oraz `FieldValue.arrayRemove`.
104
+
105
+
{% highlight kotlin %}
106
+
private fun updateData() {
107
+
val reference = database.collection("club").document("acmilan")
Usunięcie dokumentu następuje poprzez wywołanie metody `delete` na referencji dokumentu (nie powoduje usunięcia jego podkolekcji), natomiast przypisanie wartości `FieldValue.delete()` do pola w operacji `update` powoduje jego usunięcie. Usuwanie całych kolekcji po stronie klient jest niezalecane ze względu na zagrożenia wydajności, wycieku pamięci, bezpieczeńśtwa po stronie klienta wynikające z potrzeby wysyłania wielu żądań.
val reference = database.collection("club").document("acmilan")
131
+
132
+
val updates = HashMap<String, Any>()
133
+
updates["uclTrophiesYear"] = FieldValue.delete()
134
+
135
+
reference.update(updates)
136
+
//add some listeners
137
+
}
138
+
{% endhighlight %}
139
+
140
+
## Odczyt
141
+
Pobieranie dokumentów odbywa się przez wywołanie metody `get` na referencji dokumentu lub kolekcji. Dodatkowo można ustawić źródło pobierania danych na `serwer` lub pamięć `cache` oraz `parsować` otrzymane dane do instancji klasy. Rozszerzenie żądania o żłożone zapytania pozwala filtrowanie (`where`), sortowanie (`orderBy`) i ograniczanie liczby wyników spełniających założenia (`limit`).
142
+
143
+
{% highlight kotlin %}
144
+
private fun getDocument() {
145
+
val reference = database.collection("club").document("acmilan")
146
+
147
+
//add optional source and listeners and retrieve document
148
+
val source = Source.SERVER //change to Source.CACHE for cached data
Ponadto istnieje możliwość nasłuchiwania modyfikacji danych dla dokumentu i kolekcji w czasie rzeczywistym poprzez dodanie obiektu słuchacza z uwzględnieniem źródła i typu zmian.
183
+
184
+
{% highlight kotlin %}
185
+
private fun listenForDocumentChanges() {
186
+
val reference = database.collection("club").document("acmilan")
if (snapshot != null && snapshot.metadata.hasPendingWrites()) {
194
+
//local changes
195
+
}
196
+
else {
197
+
//server changes
198
+
}
199
+
200
+
//check type of the change
201
+
for (changes in snapshots!!.documentChanges) {
202
+
//could be: DocumentChange.Type.ADDED, MODIFIED or REMOVED
203
+
}
204
+
})
205
+
206
+
//do the same on the multiple documents from collection to listen more documents
207
+
}
208
+
{% endhighlight %}
71
209
72
210
## Transakcje
73
-
//TODO
211
+
Cloud Firestore wspiera atomowe operacje dla zapisu i odczytu, które są implikowane tylko wtedy kiedy wszystkie operacje zbioru zakończą się pozytywnie, zatem wykonanie zbioru operacji atomowych jest spójne i nierozdzielne. Wyróżnia się dwa typy operacji atomowych: `transakcje` (`transaction`) - zbiór operacji odczytu i zapisu na wielu dokumentach oraz `zestaw zapisu` (`batched write`) - zbiór operacji zapisu dla wielu dokumentów. Transakcje pozwalają na grupowanie wielu operacji w jedną transakcje i wykorzystywane są przede wszystkim do modyfikacji dokumentów bazując na ich bieżącym stanie. Wykonywane są za pomocą metody `runTransaction` lub zbioru operacji zapisu na obiekcie `WriteBatch`.
212
+
213
+
{% highlight kotlin %}
214
+
private fun makeTransaction() {
215
+
val reference = database.collection("club").document("acmilan")
0 commit comments