nosql-tutorial 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,116 @@
1
+ #### {% title "CouchDB — Futon" %}
2
+
3
+ # CouchDB — Futon
4
+
5
+ Graficzny interfejs do CouchDB jest dostępny z URI:
6
+
7
+ http://127.0.0.1:5984/_utils/
8
+
9
+ albo:
10
+
11
+ http://localhost:5984/_utils/
12
+
13
+ Korzystamy z nakładki Futon aby utworzyć i usunąć bazę danych,
14
+ dodajemy i usuwamy dokument z bazy danych, dodajemy i usuwamy
15
+ załącznik. Tworzymy tymczasowy widok.
16
+
17
+
18
+ ## Tworzymy bazę i dodajemy do niej dokumenty
19
+
20
+ Tworzymy prostą bazę danych *sprawdziany*:
21
+
22
+ curl -X PUT http://127.0.0.1:5984/sprawdziany
23
+
24
+ w której będziemy zapisywać takie dokumenty:
25
+
26
+ nazwa: "jakie?"
27
+ wyniki: { "login1":wynik1, ...}
28
+
29
+ Dodajemy kilka dokumentów do bazy danych.
30
+ Tak to można zrobić z wiersza poleceń:
31
+
32
+ curl -X POST -d @sprawdziany.json http://127.0.0.1:5984/sprawdziany/_bulk_docs
33
+
34
+ gdzie w pliku *sprawdziany.json* wpisaliśmy:
35
+
36
+ :::json
37
+ {
38
+ "docs": [
39
+ {"_id":"1", "nazwa":"html", "wyniki":{"jacek":10, "agatka":20}},
40
+ {"_id":"2", "nazwa":"css", "wyniki":{"jacek":1, "agatka":12}},
41
+ {"_id":"3", "nazwa":"js", "wyniki":{"jacek":1, "agatka":12}}
42
+ ]
43
+ }
44
+
45
+ Możemy też dodać kilka dokumentów, korzystając z *Futona*. **Jak?**
46
+
47
+
48
+ ## Tymczasowe widoki
49
+
50
+ Tutaj:
51
+
52
+ http://127.0.0.1:5984/_utils/index.html
53
+
54
+ jest lista baz. A tutaj baza *sprawdziany*:
55
+
56
+ http://127.0.0.1:5984/_utils/database.html?sprawdziany
57
+
58
+ Tworzymy widok tymczasowy (lista rozwijana, prawy górny róg):
59
+ wybieramy **Temporary view**. Domyślny widok definiuje funkcja:
60
+
61
+ :::javascript
62
+ function(doc) {
63
+ emit(null, doc);
64
+ }
65
+
66
+ Uruchamiamy wpisaną *Map Function*.
67
+ Czy można odgadnąć czym jest argument *doc* tej funkcji?
68
+
69
+ W okienku *View Code* wpisujemy naszą pierwszą *Map Function*:
70
+
71
+ :::javascript
72
+ function(doc) {
73
+ var login, wynik, value;
74
+ if (doc.nazwa && doc.wyniki) {
75
+ for (login in doc.wyniki) {
76
+ wynik = doc.wyniki[login];
77
+ value = [login, doc.nazwa, wynik];
78
+ emit(wynik, value);
79
+ }
80
+ }
81
+ }
82
+
83
+ Sortowanie po wynikach. Jak posortować po *loginach*? (proste)
84
+
85
+ Druga funkcja map:
86
+
87
+ :::javascript
88
+ function(doc) {
89
+ var wynik, key;
90
+ if (doc.nazwa && doc.wyniki) {
91
+ for (var login in doc.wyniki) {
92
+ wynik = doc.wyniki[login];
93
+ key = [doc.nazwa, wynik];
94
+ emit(key, login);
95
+ }
96
+ }
97
+ }
98
+
99
+ Teraz sortowanie jest po `[doc.nazwa, wynik]`. Co to oznacza?
100
+
101
+
102
+ ## Konfiguracja
103
+
104
+ Jeśli w konfiguracji **httpd > bind address** zmienimy 127.0.0.1
105
+ na 0.0.0.0, to uzyskamy zdalny dostęp do Futona
106
+ i CouchDB. (Ale stracimy dostęp lokalny.)
107
+
108
+
109
+ ## Replikacja bazy danych
110
+
111
+ Do czego może się przydać?
112
+
113
+
114
+ ## Compacting database
115
+
116
+ Ważne! Dlaczego?
@@ -0,0 +1,53 @@
1
+ #### {% title "CouchDB – Ruby" %}
2
+
3
+ # CouchDB – Ruby
4
+
5
+ ## Korzystamy z gemu *rest-client*
6
+
7
+ Przykład z Wiki: [collation](http://wiki.apache.org/couchdb/View_collation):
8
+
9
+ :::ruby
10
+ # file: collseq.rb
11
+ require 'rubygems'
12
+ require 'restclient'
13
+ require 'json'
14
+
15
+ DB="http://127.0.0.1:5984/collator"
16
+ RestClient.delete DB rescue nil
17
+ RestClient.put "#{DB}",""
18
+ (32..126).each do |c|
19
+ RestClient.put "#{DB}/#{c.to_s(16)}", {"x"=>c.chr}.to_json
20
+ end
21
+ RestClient.put "#{DB}/_design/test", <<EOS
22
+ {
23
+ "views":{
24
+ "one":{
25
+ "map":"function (doc) { emit(doc.x,null); }"
26
+ }
27
+ }
28
+ }
29
+ EOS
30
+ puts RestClient.get("#{DB}/_design/test/_view/one")
31
+
32
+ ## Couchrest & irb
33
+
34
+ :::ruby
35
+ db = CouchRest.database!("http://localhost:5984/my_db")
36
+ attr = { "imie" => "Włodek", "login" => "wbzyl", "wiek" => "18" }
37
+ result = db.save_doc(attr)
38
+
39
+ Dalej
40
+
41
+ :::ruby
42
+ result['id']
43
+ record = db.get(result['id'])
44
+ record['_rev']
45
+ record['login'] = 'matwb'
46
+ result = db.save_doc(record)
47
+ record = db.get(result['id'])
48
+ db.delete_doc(record)
49
+
50
+
51
+ Zob. [Contacts](http://gist.github.com/112109),
52
+ [blog J. P. Wood’a](http://johnpwood.net/tag/couchrest/),
53
+ [Rails Wiki: CouchDB](http://wiki.rubyonrails.org/database-support/couchdb).
@@ -0,0 +1,162 @@
1
+ #### {% title "CouchDB — Widoki" %}
2
+
3
+ # CouchDB — Widoki
4
+
5
+ Zapytania SQL, takie jak to:
6
+
7
+ SELECT name, email, fax FROM contacts
8
+
9
+ nie mają sensu dla dokumentowych baz danych.
10
+
11
+ Dlaczego? Rozważyć wartości NULL. Rekordy w tabelach SQL a dokumenty w
12
+ dokumentowych bazach danych.
13
+
14
+ W dokumentowych bazach danych zamiast pisać zapytania
15
+ piszemy widoki. Cytat:
16
+ „Views are the primary tool used for querying and reporting on CouchDB
17
+ documents. There are two different kinds of views: permanent and
18
+ temporary views.”
19
+
20
+ Widoki są zapisywane w bazie jako specjalne **design documents**.
21
+ Widoki są powielane z zwykłymi dokumentami.
22
+
23
+
24
+ ## Widoki w CouchDB API
25
+
26
+ Tymczasowy widok, np. taki:
27
+
28
+ :::javascript
29
+ function(doc) {
30
+ emit(doc._id, doc);
31
+ }
32
+
33
+ wywołujemy z wiersza poleceń w taki sposób:
34
+
35
+ curl -X POST http://127.0.0.1:5984/sprawdziany/_temp_view \
36
+ -d '{"map":"function(doc) { emit(doc._id, doc); }"}'
37
+
38
+ Widok permanentny wstawiamy do bazy
39
+ z *id* **_design/*nazwa_widoku*** w taki sposób:
40
+
41
+ curl -X PUT http://127.0.0.1:5984/sprawdziany/_design/wyniki -d @ja.json
42
+
43
+ gdzie plik *ja.json* ma następującą zawartość:
44
+
45
+ :::json
46
+ {
47
+ "language": "javascript",
48
+ "views": {
49
+ "wyniki_jacka": {
50
+ "map": "function(doc) {
51
+ if (doc.nazwa && doc.wyniki['jacek']) {
52
+ emit(doc.nazwa, doc.wyniki['jacek']);
53
+ }
54
+ }"
55
+ },
56
+ "wyniki_agatki": {
57
+ "map": "function(doc) {
58
+ if (doc.nazwa && doc.wyniki['agatka']) {
59
+ emit(doc.nazwa, doc.wyniki['agatka']);
60
+ }
61
+ }"
62
+ }
63
+ }
64
+ }
65
+
66
+ Widoki permanentne wywołujemy inaczej (GET zamiast POST):
67
+
68
+ curl -X GET http://127.0.0.1:5984/sprawdziany/_design/wyniki/_view/wyniki_jacka
69
+ curl -X GET http://127.0.0.1:5984/sprawdziany/_design/wyniki/_view/wyniki_agatki
70
+
71
+ Ale łatwiejszy w dalszej obróbce byłby taki widok:
72
+
73
+ :::javascript
74
+ function(doc) {
75
+ if (doc.nazwa && doc.wyniki['jacek']) {
76
+ emit(doc._id, {"sprawdzian":doc.nazwa, "punkty":doc.wyniki['jacek']});
77
+ }
78
+ }
79
+
80
+ ## „Złączenia” w bazach CouchDB
81
+
82
+ Example: how you'd go about modeling a simple blogging system with “post” and
83
+ “comment” entities, where any blog post might have many comments.
84
+
85
+ Przykład z artykułu:
86
+ Christopher Lenz, [CouchDB "Joins"](http://www.cmlenz.net/archives/2007/10/couchdb-joins).
87
+
88
+ ### Komentarze inline
89
+
90
+ Utworzymy bazę zawierającą kilka takich dokumentów:
91
+
92
+ :::json
93
+ {
94
+ "author": "jacek",
95
+ "title": "Rails 2",
96
+ "content": "Bla bla…",
97
+ "comments": [
98
+ {"author": "agatka", "content": "…"},
99
+ {"author": "bolek", "content": "…"}
100
+ ]
101
+ }
102
+
103
+ Dane do umieścimy w bazie za pomocą skryptu
104
+ {%= link_to 'blog-inline.rb', '/doc/couchdb/blog-inline.rb' %}.
105
+
106
+ Widok:
107
+
108
+ :::javascript
109
+ function(doc) {
110
+ for (var i in doc.comments) {
111
+ emit(doc.comments[i].author, doc.comments[i].content);
112
+ }
113
+ }
114
+
115
+ Jakie problemy może dawać takie podejście?
116
+
117
+
118
+ ### Komentarze w osobnych dokumentach:
119
+
120
+ Utworzymy bazę zawierającą kilka postów:
121
+
122
+ :::json
123
+ {
124
+ "_id": "01"
125
+ "type": "post",
126
+ "author": "jacek",
127
+ "title": "Rails 3",
128
+ "content": "Bla bla bla …"
129
+ }
130
+
131
+ oraz komentarzy:
132
+
133
+ :::json
134
+ {
135
+ "type": "comment",
136
+ "post_id": "01",
137
+ "author": "agatka",
138
+ "content": "…"
139
+ }
140
+ {
141
+ "type": "comment",
142
+ "post_id": "01",
143
+ "author": "bolek",
144
+ "content": "…"
145
+ }
146
+
147
+ TODO:
148
+ Dane do umieścimy w bazie za pomocą skryptu
149
+ {%= link_to 'blog-separate.rb', '/doc/couchdb/blog-separate.rb' %}.
150
+
151
+ Poniższy widok, wypisuje komentarze zgrupowane po *post_id*:
152
+
153
+ :::javascript
154
+ function(doc) {
155
+ if (doc.type == "comment") {
156
+ emir(doc.post_id, {author: doc.author, content: doc.content});
157
+ }
158
+ }
159
+
160
+ Sprawdzić powyższe stwierdzenie.
161
+
162
+ Takie podejście ma swoje braki. Jakie?
@@ -0,0 +1,122 @@
1
+ #### {% title "CouchDB – Zaczynamy" %}
2
+
3
+ # CouchDB – Zaczynamy
4
+
5
+ Co to są [dokumentowe bazy danych] [document-oriented database]?
6
+
7
+ Dlaczego korzystamy z dokumentowych baz danych:
8
+
9
+ 1. Dokumentowe systemy baz danych są **schema-free**.
10
+ 1. Another advantage of document oriented databases is **the ease of
11
+ usage and programming** so that untrained business users, for example,
12
+ can create applications and design their own databases. Information
13
+ can be added without worrying about the "record size" and so
14
+ programmers simply need to build an interface to allow the
15
+ information to be entered easily.
16
+
17
+ Dwa cytaty ze strony [projektu CouchDB](http://couchdb.apache.org/):
18
+
19
+ „Apache CouchDB is a document-oriented database that can be queried and
20
+ indexed in a MapReduce fashion using JavaScript.”
21
+
22
+ „CouchDB provides a RESTful JSON API than can be accessed from any
23
+ environment that allows HTTP requests.”
24
+
25
+ Trochę historii:
26
+
27
+ * [Damien Katz](http://damienkatz.net/) – autor
28
+ * Przepisanie programu z C++ na Erlang – 2006
29
+ * Restful API – kwiecień 2006
30
+ * Pierwsza dostępna wersja 0.2 – sierpień 2006
31
+ * Przejście z XML na JSON, Javascript językiem zapytań – sierpień 2007
32
+ * [Map/Reduce][map-reduce] – luty 2008
33
+
34
+
35
+ ## Instalacja serwera CouchDB
36
+
37
+ Najłatwiej jest zainstalować serwer z pakietu:
38
+
39
+ * Fedora: `su –c 'yum install couchdb'`
40
+ * Ubuntu: ???
41
+
42
+ Sprawdzamy, czy instalacja przebiegła bez błędów:
43
+
44
+ curl http://127.0.0.1:5984/
45
+ => {"couchdb":"Welcome","version":"0.11.0b"}
46
+
47
+ Na koniec wchodzimy na stronę:
48
+
49
+ http://127.0.0.1:5984/_utils/
50
+
51
+ gdzie jest dostępny *Futon*, czyli narzędzie do administracji bazami
52
+ danych zarządzanymi przez CouchDB.
53
+
54
+ Klikając w odpowiednie zakładki *Futona* możemy wyświetlić
55
+ listę zainstalowanych baz danych, szczegóły konfiguracji itd.
56
+
57
+ Ale informacje te można też uzyskać inaczej, korzystając
58
+ z na przykład programu *curl*:
59
+
60
+ curl -X GET http://127.0.0.1:5984/_all_dbs
61
+ curl -X GET http://127.0.0.1:5984/_config
62
+
63
+ Na koniec kilka innych zapytań:
64
+
65
+ curl -X GET http://127.0.0.1:5984/_uuids?count=2
66
+ curl -X POST http://127.0.0.1:5984/_replicate?source=xxx&target=yyy
67
+
68
+ W odpowiedzi na każde żądanie HTTP (*request*), dostajemy
69
+ odpowiedź HTTP (*response*) w formacie [JSON][json].
70
+
71
+ **Co to jest:** HTTP request, HTTP response, format wymiany danych JSON?
72
+
73
+ Jeśli skorzystamy z opcji `-v` programu *curl*
74
+ to program wypisze szczegóły tego co robi, na przykład:
75
+
76
+ curl -vX POST http://127.0.0.1:5984/_replicate?source=xxx&target=yyy
77
+
78
+ (Chociaż tutaj *content-type* jest ustawiony na *text/plain;charset=utf-8*.
79
+ Dlaczego?)
80
+
81
+ [json]: http://www.json.org/ "JSON"
82
+
83
+
84
+ ## CRUD na bazach danych
85
+
86
+ CRUD to skrót od pierwszych liter słów:
87
+ Create, Read, Update, Delete.
88
+
89
+ Poniżej zobaczymy jak korzystając z programu *curl*
90
+ utworzyć nową bazę danych, usunąć bazę, pobrać informację o bazie
91
+ itd. Skorzystam ze ściągi:
92
+
93
+ * [Ściąga z API: Database level](http://wiki.apache.org/couchdb/API_Cheatsheet)
94
+
95
+ Tworzymy nową bazę o nazwie *xxx*:
96
+
97
+ curl -X PUT http://127.0.0.1:5984/xxx
98
+
99
+ Pobieramy info o bazie *xxx*:
100
+
101
+ curl -X GET http://127.0.0.1:5984/xxx
102
+
103
+ Usuwamy bazę *xxx*:
104
+
105
+ curl -X DELETE http://127.0.0.1:5984/xxx
106
+
107
+ Nie ma polecenia dla *Update*.
108
+ Omówić pozostałe operacje ze ściągi: *Database level*
109
+
110
+ **REST** to akronim od *Represenational State Transfer*.
111
+ Zwykle w kontekście WWW rozumiemy ten skrót tak:
112
+
113
+ * Dane są zasobami (ang. resources)
114
+ * Każdy zasób ma swój unikalny URI
115
+ * Na zasobach można wykonywać cztery podstawowe operacje CRUD
116
+ * Klient i serwer komunikują się ze sobą korzystając protokołu
117
+ bezstanowego. Oznacza to, że klient zwraca się z żądaniem do
118
+ serwera. Serwer odpowiada i cała konwersacja się kończy.
119
+
120
+
121
+ [document-oriented database]: http://en.wikipedia.org/wiki/Document-oriented_database "Document-oriented database"
122
+ [map-reduce]: http://en.wikipedia.org/wiki/MapReduce "MapReduce"