2. Agenda
• Lavorare con I documenti
• Requisiti dell’Applicazione
• Iterazione di Schema design
• Architettura dell’applicazione di esempio ‘myCMS’ e
frammenti di codice
• ‘Genius Bar’ Q&Acon il team italiano di MongoDB
5. Documento di Esempio
{
‘_id’ : ObjectId(..),
‘title’: ‘Schema design in MongoDB’,
‘author’: ‘massimobrignoli’,
‘text’: ‘I dati in MongoDB hanno uno schema flessibile..’,
‘date’ : ISODate(..),
‘tags’: [‘MongoDB’, ‘schema’],
‘comments’: [ { ‘text ‘ : ‘Molto utile!!.’, ts: ISODate(..) } ]
}
6. Requisiti del ‘myCMS’
• E’ composto da diversi tipi di articoli categorizzati.
• Gli Utenti possono registrarsi come memobri, fare login,
modificare il loro profilo e fare logout.
• Gli Utenti possono pubblicare nuovi articoli e commentare gli
articoli.
• Il sistema raccoglie e analizza statistiche di utilizzo –
pubblicazione di articoli, visite e interazioni – da pubblicare sul
sito o per gli admin.
7. Le Entità del ‘myCMS’
• Articoli
• Diversi tipi: blog, gallerie di immagini, sondaggi
• Contengono file multimediali (immagini, video)
• Sono taggati
• Utenti
• Ognuno avrà un profilo
• Interazioni degli Utenti
• Commenti
• Visite
13. Modellazione dei commenti (1)
• Si possono fare 2 collections – articles e
comments
• Usare una reference (i.e. foreign key) per collegarli
• Ma... saranno necessarie N+1 query per restituire
l’articolo e i commenti (sono N è il # di commenti){
‘_id’: ObjectId(..),
‘title’: ‘Schema design in MongoDB’,
‘author’: ‘massimobrignoli’,
‘date’: ISODate(..),
‘tags’: [‘MongoDB’, ‘schema’],
‘section’: ‘schema’,
‘slug’: ‘schema-design-in-mongodb’,
‘comments’: [ ObjectId(..),…]
}
{ ‘_id’: ObjectId(..),
‘article_id’: 1,
‘text’: ‘Un grande articolo, mi ha
aiutato a capire lo schema
design’,
‘date’: ISODate(..),,
‘author’: ‘johnsmith’
}
14. Modellazione dei commenti (2)
• Una sola collection degli
articoli. I commenti sono
incapsulati.
• Pregi
• Singola query, il documento è
disegnato per l’accesso il
lettura
• Localizzazione dei dato (disco,
shard)
• Difetti
• L’array dei commenti e’ senza
limiti. I documenti possono
crescere in dimensione oltre I
16MB
{
‘_id’: ObjectId(..),
‘title’: ‘Schema design in MongoDB’,
‘author’: ‘massimobrignoli’,
‘date’: ISODate(..),
‘tags’: [‘MongoDB’, ‘schema’],
…
‘comments’: [
{
‘text’: ‘Un grande articolo,
mi ha aiutatoa capire lo
schema design’,
‘date’: ISODate(..),
‘author’: ‘johnsmith’
},
…
]
}
15. Modellazione dei commenti (3)
• Un’altra opzione: un ibrido delle proposte (1)
e (2): incapsulare i top commenti (per data o
popolarità) nel documento dell’articolo.
• Array dei commenti di grandezza fissa (feature 2.4)
• Tutti gli altri commenti sono scritti in una collection di
commenti in gruppi
• Vantaggi:
– Il documento ha la dimensione quasi fissata => meno
spostamenti sul disco
– Una singola query restituisce tutto il documento
– Rimane tutta la storia dei commenti con possibilità di analisi
16. Modellazione dei commenti (3)
{
‘_id’: ObjectId(..),
‘title’: ‘Schemadesignin MongoDB’,
‘author’: ‘mattbates’,
‘date’: ISODate(..),
‘tags’:[‘MongoDB’,‘schema’],
…
‘comments_count’:45,
‘comments_pages’: 1
‘comments’: [
{
‘text’: ‘Agreat article, helped me
understandschema design’,
‘date’: ISODate(..),
‘author’: ‘johnsmith’
},
…
]
}
Numero totale dei
commenti
• Intero aggiornatodall’operazione
diupdatequandoI commenti
sonoaggiunti/rimossi
Numero di pagine
Intero aggiornatodall’operazionedi
updatequandoI commentisono
aggiunti/rimossi
Array a dimensione fissa
per i commenti:
• I10 piùrecenti
• Ordinatoper data in fase di
inserimento
17. Modellazione dei commenti (3)
{
‘_id’: ObjectId(..),
‘article_id’: ObjectId(..),
‘page’: 1,
‘count’: 42
‘comments’: [
{
‘text’: ‘Agreat article, helped me
understand schema design’,
‘date’: ISODate(..),
‘author’: ‘johnsmith’
},
…
}
Un gruppo di commenti
contiene fino a 100
commenti
E’un array di 100 commenti,che
sono subdocumenti
18. Modellazione delle interazioni
• Interazioni
– Visualizzazioni degli articoli
– Commenti
– (Condivisione sui social media)
• Requisiti
– Time serie
– Pre-aggregazione in preparazione della parte analitica
19. Modellazione delle interazioni
• Documento per articolo per
giorno: raggruppamento
• Contatore giornaliero e contatori
nei sotto-documenti orari delle
interazioni
• Array a dimensione fissa (24 ore)
• Basta una singola query per
avere tutte le interazioni di un
articolo in un giorno.
{
‘_id’: ObjectId(..),
‘article_id’: ObjectId(..),
‘section’: ‘schema’,
‘date’: ISODate(..),
‘daily’: { ‘views’: 45, ‘comments’:
150 }
‘hours’: {
0 : { ‘views’: 10 },
1 : { ‘views’: 2 },
…
23 : { ‘comments’: 14, ‘views’: 10
}
}
}
20. JSON e RESTful API
Client-side
JSON
(eg AngularJS) (BSON)
Le applicazioni reali non sono fatte in una shell – Costruiamo
un’interfaccia RESTful.
Pymongo
driver
Python web
app
HTTP(S) REST
Gli esempi che seguiranno: Python RESTful API usando Flask
microframework
21. myCMS REST punti di accesso
Method URI Action
GET /articles Restituisce tutti gli articoli
GET /articles-by-tag/[tag] Restituisce tutti gli articoli con una tag
GET /articles/[article_id] Restituisce un articolo tramite article_id
POST /articles Aggiunge un nuovo articolo
GET /articles/[article_id]/comments Restituisce tutti i commenti di un
articolo tramite article_id
POST /articles/[article_id]/comments Aggiunge un nuovo commento a un
articolo
POST /users Registra un utente
GET /users/[username] Restituisce il profilo di un utente
PUT /users/[username] Aggiorna il profilo di un utente
22. $ git clone http://www.github.com/mattbates/mycms-mongodb
$ cd mycms-mongodb
$ virtualenv venv
$ source venv/bin/activate
$ pip install –r requirements.txt
$ mkdir –p data/db
$ mongod --dbpath=data/db –fork --logpath=mongod.log
$ python web.py
($ deactivate)
Partiamo con lo scheletro del
codice
23. @app.route('/cms/api/v1.0/articles', methods=['GET'])
def get_articles():
"""Retrieves all articles in the collection
sorted by date
"""
# query all articles and return a cursor sorted by date
cur = db['articles'].find().sort({'date’:1})
if not cur:
abort(400)
# iterate the cursor and add docs to a dict
articles = [article for article in cur]
return jsonify({'articles' : json.dumps(articles, default=json_util.default)})
Metodi dell’interfaccia RESTful in
Python + Flask
24. @app.route('/cms/api/v1.0/articles/<string:article_id>/comments', methods = ['POST'])
def add_comment(article_id):
"""Adds a comment to the specified article and a
bucket, as well as updating a view counter
"””
…
page_id = article['last_comment_id'] // 100
…
# push the comment to the latest bucket and $inc the count
page = db['comments'].find_and_modify(
{ 'article_id' : ObjectId(article_id),
'page' : page_id},
{ '$inc' : { 'count' :1 },
'$push' : {
'comments' : comment } },
fields= {'count':1},
upsert=True,
new=True)
Metodi dell’interfaccia RESTful in
Python + Flask
25. # $inc the page count if bucket size (100) is exceeded
if page['count'] > 100:
db.articles.update(
{ '_id' : article_id,
'comments_pages': article['comments_pages'] },
{ '$inc': { 'comments_pages': 1 } } )
# let's also add to the article itself
# most recent 10 comments only
res = db['articles'].update(
{'_id' : ObjectId(article_id)},
{'$push' : {'comments' : { '$each' : [comment],
'$sort' : {’date' : 1 },
'$slice' : -10}},
'$inc' : {'comment_count' : 1}})
…
Metodi dell’interfaccia RESTful in
Python + Flask
26. def add_interaction(article_id, type):
"""Record the interaction (view/comment) for the
specified article into the daily bucket and
update an hourly counter
"""
ts = datetime.datetime.utcnow()
# $inc daily and hourly view counters in day/article stats bucket
# note the unacknowledged w=0 write concern for performance
db['interactions'].update(
{ 'article_id' : ObjectId(article_id),
'date' : datetime.datetime(ts.year, ts.month, ts.day)},
{ '$inc' : {
'daily.views' : 1,
'hourly.{}.{}'.format(type, ts.hour) : 1
}},
upsert=True,
w=0)
Metodi dell’interfaccia RESTful in
Python + Flask
27. $ curl -i http://localhost:5000/cms/api/v1.0/articles
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 20
Server: Werkzeug/0.9.4 Python/2.7.6
Date: Sat, 01 Feb 2014 09:52:57 GMT
{
"articles": "[{"author": "mattbates", "title": "Schema design in MongoDB",
"text": "Data in MongoDB has a flexible schema..", "tags": ["MongoDB",
"schema"], "date": {"$date": 1391293347408}, "_id": {"$oid":
"52ed73a30bd031362b3c6bb3"}}]"
}
Testiamo l’API– Ritorno di articoli
28. $ curl -H "Content-Type: application/json" -X POST -d '{"text":"An interesting
article and a great read."}'
http://localhost:5000/cms/api/v1.0/articles/52ed73a30bd031362b3c6bb3/comment
s
{
"comment": "{"date": {"$date": 1391639269724}, "text": "An interesting
article and a great read."}”
}
Testiamo l’API – Inserire un
commento
29. Iterazioni con lo Schema
Avete una nuova feature nella lista di cose da fare?
I Documenti hanno uno schema dinamico, quindi
possiamo semplicemente iterare l’oggetto.
>>> user = { ‘username’: ‘massimo’,
‘first’ : ‘Massimo’,
‘last’ : ‘Brignoli’,
‘preferences’: { ‘opt_out’: True } }
>>> user..save(user)
33. Conclusioni
• Documenti a schema flessibile con l’abilità di
incapsulare strutture dati ricche e complesse,
ottimizzate per massimizare le performance.
• Lo Schema è disegnato attorno agli schema di
accesso ai dati e non per ottimizzare lo storage.
• Usate il Referencing per maggiore flessibilità
• Sviluppate lo schema con in mente la scalabilità
orizzontale, è importante considerare la sharding
key
34. Approfondimenti
• Il codice sorgente di ‘myCMS’
:http://www.github.com/mattbates/mycms-mongodb
• Use case - metadata and asset management:
http://docs.mongodb.org/ecosystem/use-
cases/metadata-and-asset-management/
• Use case - storing
comments:http://docs.mongodb.org/ecosystem/use-
cases/storing-comments/
35. Prossima Sessione – 8 Aprile
Interagire con il database
– Il linguaggio delle query e update
– Le interazioni tra l’applicazionee il database
• Esempi di Codice
In the filing cabinet model, the patient’s x-rays, checkups, and allergies are stored in separate drawers and pulled together (like an RDBMS)In the file folder model, we store all of the patient information in a single folder (like MongoDB)
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
PriorityFloating point number between 0..1000Highest member that is up to date wins Up to date == within 10 seconds of primaryIf a higher priority member catches up, it will force election and win Slave DelayLags behind master by configurable time delay Automatically hidden from clientsProtects against operator errorsFat fingeringApplication corrupts data
Large scale operation can be combined with high performance on commodity hardware through horizontal scalingBuild - Document oriented database maps perfectly to object oriented languagesScale - MongoDB presents clear path to scalability that isn't ops intensive - Provides same interface for sharded cluster as single instance