session 02 - schema design e architettura

36
Serie Application Development Back to Basics Schema Design Senior Solutions Architects, MongoDB Inc. Massimo Brignoli #MongoDBBasicsIT

Upload: mongodb

Post on 07-Jul-2015

925 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Session 02 - schema design e architettura

Serie Application Development Back to Basics – Schema Design

Senior Solutions Architects, MongoDB Inc.

Massimo Brignoli

#MongoDBBasicsIT

Page 2: Session 02 - schema design e architettura

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&A con il team italiano di MongoDB

Page 3: Session 02 - schema design e architettura

Il Linguaggio

RDBMS MongoDB

Database ➜ Database

Table ➜ Collection

Row ➜ Document

Index ➜ Index

Join ➜ Embedded Document

Foreign Key ➜ Reference

Page 4: Session 02 - schema design e architettura

Modellare i Dati

Page 5: Session 02 - schema design e architettura

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(..) } ]

}

Page 6: Session 02 - schema design e architettura

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.

Page 7: Session 02 - schema design e architettura

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

Page 8: Session 02 - schema design e architettura

Tipico ERD (Diagramma Entità-Relazioni)

* Note: this is an illustrative example.

Page 9: Session 02 - schema design e architettura

# Python dictionary (or object)

>>> article = { ‘title’ : ‘Schema design in MongoDB’,

‘author’ : ‘massimobrignoli’,

‘section’ : ‘schema’,

‘slug’ : ‘schema-design-in-mongodb’,

‘text’ : ‘I dati in MongoDB hanno uno schema dinamico.’,

‘date’ : datetime.datetime.utcnow(),

‘tags’ : [‘MongoDB’, ‘schema’] }

>>> db[‘articles’].insert(article)

Design schema.. usando codicesorgente

Page 10: Session 02 - schema design e architettura

>>> img_data = Binary(open(‘article_img.jpg’).read())

>>> article = { ‘title’ : ‘Schema design in MongoDB’,

‘author’ : ‘massimobrignoli’,

‘section’ : ‘schema’,

‘slug’ : ‘schema-design-in-mongodb’,

‘text’ : ‘I dati in MongoDB hanno uno schema dinamico.’,

‘date’ : datetime.datetime.utcnow(),

‘tags’ : [‘MongoDB’, ‘schema’],

‘headline_img’ : {

‘img’ : img_data,

‘caption’ : ‘Documento di esempio’

}}

>>> db[‘articles’].insert(article)

Aggiungiamo un’immagine…

Page 11: Session 02 - schema design e architettura

>>> article = { ‘title’ : ‘Il mio favorito framework per lo sviluppo web’,

‘author’ : ‘massimobrignoli’,

‘section’ : ‘web-dev’,

‘slug’ : ‘web-app-frameworks’,

‘gallery’ : [

{ ‘img_url’ : ‘http://x.com/45rty’, ‘caption’ : ‘Flask’, ..},

..

]

‘date’ : datetime.datetime.utcnow(),

‘tags’ : [‘MongoDB’, ‘schema’],

}

>>> db[‘articles’].insert(article)

E diversi tipi di articolo

Page 12: Session 02 - schema design e architettura

>>> user= { ‘user’ : ‘massimobrignoli’,

‘email’ : ‘[email protected]’,

‘password’ : ‘passwordsegretissima’,

‘joined’ : datetime.datetime.utcnow()

‘location’ : { ‘city’ : ‘Cornaredo’ },

}

>>> db[‘users’].insert(user)

Utenti e Profili

Page 13: Session 02 - schema design e architettura

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’

}

Page 14: Session 02 - schema design e architettura

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 aiutato a capire lo

schema design’,

‘date’ : ISODate(..),

‘author’ : ‘johnsmith’

},

]

}

Page 15: Session 02 - schema design e architettura

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

Page 16: Session 02 - schema design e architettura

Modellazione dei commenti (3){

‘_id’ : ObjectId(..),

‘title’ : ‘Schema design in MongoDB’,

‘author’ : ‘mattbates’,

‘date’ : ISODate(..),

‘tags’ : [‘MongoDB’, ‘schema’],

‘comments_count’: 45,

‘comments_pages’ : 1

‘comments’ : [

{

‘text’ : ‘A great article, helped me

understand schema design’,

‘date’ : ISODate(..),

‘author’ : ‘johnsmith’

},

]

}

Numero totale dei

commenti• Intero aggiornato dall’operazione

di update quando I commenti

sonoaggiunti/rimossi

Numero di pagineIntero aggiornato dall’operazionedi

update quando I commenti sono

aggiunti/rimossi

Array a dimensione fissa

per i commenti:• I 10 più recenti

• Ordinato per data in fase di

inserimento

Page 17: Session 02 - schema design e architettura

Modellazione dei commenti (3)

{

‘_id’ : ObjectId(..),

‘article_id’ : ObjectId(..),

‘page’ : 1,

‘count’ : 42

‘comments’ : [

{

‘text’ : ‘A great 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

Page 18: Session 02 - schema design e architettura

Modellazione delle interazioni

• Interazioni– Visualizzazioni degli articoli

– Commenti

– (Condivisione sui social media)

• Requisiti

– Time serie

– Pre-aggregazione in preparazione della parte analitica

Page 19: Session 02 - schema design e architettura

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

}

}

}

Page 20: Session 02 - schema design e architettura

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

appHTTP(S) REST

Gli esempi che seguiranno: Python RESTful API usando Flask

microframework

Page 21: Session 02 - schema design e architettura

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

Page 22: Session 02 - schema design e architettura

$ 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

Page 23: Session 02 - schema design e architettura

@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

Page 24: Session 02 - schema design e architettura

@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

Page 25: Session 02 - schema design e architettura

# $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

Page 26: Session 02 - schema design e architettura

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

Page 27: Session 02 - schema design e architettura

$ 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

Page 28: Session 02 - schema design e architettura

$ 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

Page 29: Session 02 - schema design e architettura

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)

Page 30: Session 02 - schema design e architettura

Scale out with sharding

Page 31: Session 02 - schema design e architettura
Page 32: Session 02 - schema design e architettura
Page 33: Session 02 - schema design e architettura

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

Page 34: Session 02 - schema design e architettura

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/

Page 35: Session 02 - schema design e architettura

Prossima Sessione – 8 Aprile

Interagire con il database– Il linguaggio delle query e update

– Le interazioni tra l’applicazione e il database

• Esempi di Codice

Page 36: Session 02 - schema design e architettura

#MongoDBBasicsIT

Grazie!

Q&A con il team italiano di MongoDB