SlideShare a Scribd company logo
VALIDATED DOCUMENTS ON
MONGODB WITH MING
Alessandro Molina
@__amol__
amol@turbogears.org
Who am I
● CTO @ Axant.it, mostly Python company
(with some iOS and Android)
● TurboGears development team member
● Contributions to Ming project ODM layer
● Really happy to be here at PyConUK!
○ I thought I would have crashed my car driving on
the wrong side!
MongoDB Models
● Schema free
○ It looks like you don’t have a schema, but your
code depends on properties that need to be there.
● SubDocuments
○ You know that a blog post contain a list of
comments, but what it is a comment?
● Relations
○ You don’t have joins and foreign keys, but you still
need to express relationships
What’s Ming?
● MongoDB toolkit
○ Validation layer on pymongo
○ Manages schema migrations
○ In Memory MongoDB
○ ODM on top of all of those
● Born at sourceforge.net
● Supported by TurboGears
community
MongoDB
PyMongo
Ming
Ming.ODM
Getting Started with the ODM
● Ming.ODM looks like SQLAlchemy
● UnitOfWork
○ Avoid half-saved changes in case of crashes
○ Flush all your changes at once
● IdentityMap
○ Same DB objects are the same object in memory
● Supports Relations
● Supports events (after_insert, before_update, …)
Declaring Schema with the ODM
class WikiPage(MappedClass):
# Metadata for the collection
# like its name, indexes, session, ...
class __mongometa__:
session = DBSession
name = 'wiki_page'
unique_indexes = [('title',)]
_id = FieldProperty(schema.ObjectId)
title = FieldProperty(schema.String)
text = FieldProperty(schema.String)
# Ming automatically generates
# the relationship query
comments = RelationProperty('WikiComment')
class WikiComment(MappedClass):
class __mongometa__:
session = DBSession
name = 'wiki_comment'
_id = FieldProperty(schema.ObjectId)
text=FieldProperty(s.String, if_missing='')
# Provides an actual relation point
# between comments and pages
page_id = ForeignIdProperty('WikiPage')
● Declarative interface for models
● Supports polymorphic models
Querying the ODM
wp = WikiPage.query.get(title='FirstPage')
# Identity map prevents duplicates
wp2 = WikiPage.query.get(title='FirstPage')
assert wp is wp2
# manually fetching related comments
comments = WikiComment.query.find(dict(page_id=wp._id)).all()
# or
comments = wp.comments
# gets last 5 wikipages in natural order
wps = WikiPage.query.find().sort('$natural', DESCENDING).limit(5).all()
● Query language tries to be natural for both
SQLAlchemy and MongoDB users
The Unit Of Work
● Flush or Clear the pending changes
● Avoid mixing UOW and atomic operations
● UnitOfWork as a cache
wp = WikiPage(title='FirstPage', text='This is my first page')
DBSession.flush()
wp.title = "TITLE 2"
DBSession.update(WikiPage, {'_id':wp._id}, {'$set': {'title': "TITLE 3"}})
DBSession.flush() # wp.title will be TITLE 2, not TITLE 3
wp2 = DBSession.get(WikiPage, wp._id)
# wp2 lookup won’t query the database again
How Validation works
● Ming documents are validated at certain
points in their life cycle
○ When saving the document to the database
○ When loading it from the database.
○ Additionally, validation is performed when the
document is created through the ODM layer or
using the .make() method
■ Happens before they get saved for real
Cost of Validation
● MongoDB is famous for its speed, but
validation has a cost
○ MongoDB documents can contain many
subdocuments
○ Each subdocument must be validated by ming
○ Can even contain lists of multiple subdocuments
Cost of Validation benchmark
#With Validation
class User(MappedClass):
# ...
friends = FieldProperty([dict(fbuser=s.String,
photo=s.String,
name=s.String)], if_missing=[])
>>> timeit.timeit('User.query.find().all()', number=20000)
31.97218942642212
#Without Validation
class User(MappedClass):
# ...
friends = FieldProperty(s.Anything, if_missing=[])
>>> timeit.timeit('User.query.find().all()', number=20000)
23.391359090805054
#Avoiding the field at query time
>>> timeit.timeit('User.query.find({}, fields=("_id","name")).all()', number=20000)
21.58667516708374
Only query what you need
● Previous benchmark explains why it is
good to query only for fields you need to
process the current request
● All the fields you don’t query for, will still
be available in the object with None value
Evolving the Schema
● Migrations are performed lazily as the
objects are loaded from the database
● Simple schema evolutions:
○ New field: It will just be None for old entities.
○ Removed: Declare it as ming.schema.Deprecated
○ Changed Type: Declare it as ming.schema.Migrate
● Complex schema evolutions:
○ Add a migration function in __mongometa__
Complex migrations with Ming
class OldWikiPage(Document):
_id = Field(schema.ObjectId)
title = Field(str)
text = Field(str, if_missing='')
metadata = Field(dict(tags=[str], categories=[str]))
class WikiPage(Document):
class __mongometa__:
session = DBSession
name = 'wiki_page'
version_of = OldWikiPage
def migrate(data):
result = dict(data, version=1, tags=data['metadata']['tags'],
categories=data['metadata']['categories'])
del result['metadata']
return result
version = Field(1, required=True)
# … more fields ...
Testing MongoDB
● Ming makes testing easy
○ Your models can be directly imported from tests
○ Just bind the session to a DataStorage created in
your tests suite
● Ming provides MongoInMemory
○ much like sqlite://:memory:
● Implements 90% of mongodb, including
javascript execution with spidermonkey
Ming for Web Applications
● Ming can be integrated in any WSGI
framework through the ming.odm.
middleware.MingMiddleware
○ Automatically disposes open sessions at the end
of requests
○ Automatically provides session flushing
○ Automatically clears the session in case of
exceptions
Ming with TurboGears
● Provides builtin support for ming
○ $ gearbox quickstart --ming projectname
● Ready made test suite with fixtures on MIM
● Facilities to debug and benchmark Ming
queries through the DebugBar
● TurboGears Admin automatically
generates CRUD from Ming models
Debugging MongoDB
● TurboGears debugbar has builtin support
for MongoDB
○ Executed queries logging and results
○ Queries timing
○ Syntax prettifier and highlight for Map-Reduce and
$where javascript code
○ Queries tracking on logs for performance
reporting of webservices
DebugBar in action
Ming without learning MongoDB
● Transition from SQL/Relational solutions
to MongoDB can be scary first time.
● You can use Sprox to lower the learning
cost for simple applications
○ Sprox is the library that empowers TurboGears
Admin to automatically generate pages from
SQLA or Ming
Sprox ORM abstractions
● ORMProvider, provides an abstraction over
the ORM
● ORMProviderSelector, automatically
detects the provider to use from a model.
● Mix those together and you have a db
independent layer with automatic storage
backend detection.
Hands on Sprox
● Provider.query(self, entity, **kwargs) → get all objects
of a collection
● Provider.get_obj(self, entity, params) → get an object
● Provider.update(self, entity, params) → update an
object
● Provider.create(self, entity, params) → create a new
object
# Sprox (Ming or SQLAlchemy)
count, transactions = provider.query(MoneyTransfer)
transactions = DBSession.query(MoneyTransfer).all() # SQLAlchemy
transactions = MoneyTransfer.query.find().all() # Ming
Questions?

More Related Content

PDF
JS patterns
PPTX
Nightwatch 101 - Salvador Molina
PDF
JavaScript From Hell - CONFidence 2.0 2009
PDF
"The JavaScript Design Patterns You have to Know" by Rashad Majali
PDF
An Abusive Relationship with AngularJS
PPTX
Mobile architecture problems and solutions.
PDF
I thought you were my friend - Malicious Markup
PPTX
Going Offline with JS
JS patterns
Nightwatch 101 - Salvador Molina
JavaScript From Hell - CONFidence 2.0 2009
"The JavaScript Design Patterns You have to Know" by Rashad Majali
An Abusive Relationship with AngularJS
Mobile architecture problems and solutions.
I thought you were my friend - Malicious Markup
Going Offline with JS

What's hot (10)

PDF
ENIB 2015-2016 - CAI Web - S01E01- Côté navigateur 3/3 - Web components avec ...
PDF
HTML, CSS & Javascript Architecture (extended version) - Jan Kraus
PPTX
Going offline with JS (DDD Sydney)
PDF
まよいの墓(WebVR編)
PDF
Devoxx France - Web Components, Polymer et Material Design
PDF
"How to use TypeORM and stay alive", Andrii Andriiko
PDF
Pyramid of-developer-skills
PDF
ENIB 2015 2016 - CAI Web S02E01- Côté Navigateur 3/3 - Web Components avec Po...
PDF
HTML5 - The Good, the Bad, the Ugly
PDF
Copy & Pest - A case-study on the clipboard, blind trust and invisible cross-...
ENIB 2015-2016 - CAI Web - S01E01- Côté navigateur 3/3 - Web components avec ...
HTML, CSS & Javascript Architecture (extended version) - Jan Kraus
Going offline with JS (DDD Sydney)
まよいの墓(WebVR編)
Devoxx France - Web Components, Polymer et Material Design
"How to use TypeORM and stay alive", Andrii Andriiko
Pyramid of-developer-skills
ENIB 2015 2016 - CAI Web S02E01- Côté Navigateur 3/3 - Web Components avec Po...
HTML5 - The Good, the Bad, the Ugly
Copy & Pest - A case-study on the clipboard, blind trust and invisible cross-...
Ad

Viewers also liked (9)

PPTX
Tell Your Story: Select Social PR Case Studies 2015
PDF
Achieving Maximum Results from Your Hostel
PPT
Principles Of Achieving Wealth
PDF
TraDesto Financial Social Network
PPTX
Tell Your Story Capabilities & Cases 2014
PDF
PyConUK 2014 - PostMortem Debugging and Web Development Updated
PPTX
Linked in
PPT
planeamiento estratégico, paradigmas, cambio, entorno
PDF
EuroPython 2013 - Python3 TurboGears Training
Tell Your Story: Select Social PR Case Studies 2015
Achieving Maximum Results from Your Hostel
Principles Of Achieving Wealth
TraDesto Financial Social Network
Tell Your Story Capabilities & Cases 2014
PyConUK 2014 - PostMortem Debugging and Web Development Updated
Linked in
planeamiento estratégico, paradigmas, cambio, entorno
EuroPython 2013 - Python3 TurboGears Training
Ad

Similar to PyConUK2013 - Validated documents on MongoDB with Ming (20)

PDF
JavascriptMVC: Another choice of web framework
PDF
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
PPTX
Robust C++ Task Systems Through Compile-time Checks
PPTX
Using FXML on Clojure
PDF
Tech meetup: Web Applications Performance
PDF
More on gdb for my sql db as (fosdem 2016)
PDF
Joomla!Day Poland 2013 - Joomla Architecture (Ofer Cohen)
PDF
PyConIT6 - Messing up with pymongo for fun and profit
PDF
FOSDEM 2015: gdb tips and tricks for MySQL DBAs
PPTX
Go Is Your Next Language — Sergii Shapoval
PDF
Mockist vs. Classicists TDD
PDF
MongoTorino 2013 - BSON Mad Science for fun and profit
PDF
Django Mongodb Engine
PPTX
Revealing ALLSTOCKER
PDF
Deep dive into Android async operations
PDF
FrontEnd.pdf
PDF
Sharable of qualities of clean code
PDF
Критика "библиотечного" подхода в разработке под Android. UA Mobile 2016.
PDF
Mantri Presentation One
PDF
Gdb basics for my sql db as (openfest 2017) final
JavascriptMVC: Another choice of web framework
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
Robust C++ Task Systems Through Compile-time Checks
Using FXML on Clojure
Tech meetup: Web Applications Performance
More on gdb for my sql db as (fosdem 2016)
Joomla!Day Poland 2013 - Joomla Architecture (Ofer Cohen)
PyConIT6 - Messing up with pymongo for fun and profit
FOSDEM 2015: gdb tips and tricks for MySQL DBAs
Go Is Your Next Language — Sergii Shapoval
Mockist vs. Classicists TDD
MongoTorino 2013 - BSON Mad Science for fun and profit
Django Mongodb Engine
Revealing ALLSTOCKER
Deep dive into Android async operations
FrontEnd.pdf
Sharable of qualities of clean code
Критика "библиотечного" подхода в разработке под Android. UA Mobile 2016.
Mantri Presentation One
Gdb basics for my sql db as (openfest 2017) final

More from Alessandro Molina (12)

PDF
PyCon Ireland 2022 - PyArrow full stack.pdf
PDF
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PDF
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
PDF
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
PDF
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PDF
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PDF
Reactive & Realtime Web Applications with TurboGears2
PDF
Post-Mortem Debugging and Web Development
PDF
PyGrunn2013 High Performance Web Applications with TurboGears
PDF
Rapid Prototyping with TurboGears2
PDF
TurboGears2 Pluggable Applications
PDF
From SQLAlchemy to Ming with TurboGears2
PyCon Ireland 2022 - PyArrow full stack.pdf
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
Reactive & Realtime Web Applications with TurboGears2
Post-Mortem Debugging and Web Development
PyGrunn2013 High Performance Web Applications with TurboGears
Rapid Prototyping with TurboGears2
TurboGears2 Pluggable Applications
From SQLAlchemy to Ming with TurboGears2

Recently uploaded (20)

PDF
Approach and Philosophy of On baking technology
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
A Presentation on Artificial Intelligence
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
Spectroscopy.pptx food analysis technology
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
Approach and Philosophy of On baking technology
Diabetes mellitus diagnosis method based random forest with bat algorithm
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Mobile App Security Testing_ A Comprehensive Guide.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Reach Out and Touch Someone: Haptics and Empathic Computing
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
sap open course for s4hana steps from ECC to s4
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
A Presentation on Artificial Intelligence
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Network Security Unit 5.pdf for BCA BBA.
Review of recent advances in non-invasive hemoglobin estimation
Encapsulation_ Review paper, used for researhc scholars
MIND Revenue Release Quarter 2 2025 Press Release
Spectroscopy.pptx food analysis technology
Advanced methodologies resolving dimensionality complications for autism neur...

PyConUK2013 - Validated documents on MongoDB with Ming

  • 1. VALIDATED DOCUMENTS ON MONGODB WITH MING Alessandro Molina @__amol__ amol@turbogears.org
  • 2. Who am I ● CTO @ Axant.it, mostly Python company (with some iOS and Android) ● TurboGears development team member ● Contributions to Ming project ODM layer ● Really happy to be here at PyConUK! ○ I thought I would have crashed my car driving on the wrong side!
  • 3. MongoDB Models ● Schema free ○ It looks like you don’t have a schema, but your code depends on properties that need to be there. ● SubDocuments ○ You know that a blog post contain a list of comments, but what it is a comment? ● Relations ○ You don’t have joins and foreign keys, but you still need to express relationships
  • 4. What’s Ming? ● MongoDB toolkit ○ Validation layer on pymongo ○ Manages schema migrations ○ In Memory MongoDB ○ ODM on top of all of those ● Born at sourceforge.net ● Supported by TurboGears community MongoDB PyMongo Ming Ming.ODM
  • 5. Getting Started with the ODM ● Ming.ODM looks like SQLAlchemy ● UnitOfWork ○ Avoid half-saved changes in case of crashes ○ Flush all your changes at once ● IdentityMap ○ Same DB objects are the same object in memory ● Supports Relations ● Supports events (after_insert, before_update, …)
  • 6. Declaring Schema with the ODM class WikiPage(MappedClass): # Metadata for the collection # like its name, indexes, session, ... class __mongometa__: session = DBSession name = 'wiki_page' unique_indexes = [('title',)] _id = FieldProperty(schema.ObjectId) title = FieldProperty(schema.String) text = FieldProperty(schema.String) # Ming automatically generates # the relationship query comments = RelationProperty('WikiComment') class WikiComment(MappedClass): class __mongometa__: session = DBSession name = 'wiki_comment' _id = FieldProperty(schema.ObjectId) text=FieldProperty(s.String, if_missing='') # Provides an actual relation point # between comments and pages page_id = ForeignIdProperty('WikiPage') ● Declarative interface for models ● Supports polymorphic models
  • 7. Querying the ODM wp = WikiPage.query.get(title='FirstPage') # Identity map prevents duplicates wp2 = WikiPage.query.get(title='FirstPage') assert wp is wp2 # manually fetching related comments comments = WikiComment.query.find(dict(page_id=wp._id)).all() # or comments = wp.comments # gets last 5 wikipages in natural order wps = WikiPage.query.find().sort('$natural', DESCENDING).limit(5).all() ● Query language tries to be natural for both SQLAlchemy and MongoDB users
  • 8. The Unit Of Work ● Flush or Clear the pending changes ● Avoid mixing UOW and atomic operations ● UnitOfWork as a cache wp = WikiPage(title='FirstPage', text='This is my first page') DBSession.flush() wp.title = "TITLE 2" DBSession.update(WikiPage, {'_id':wp._id}, {'$set': {'title': "TITLE 3"}}) DBSession.flush() # wp.title will be TITLE 2, not TITLE 3 wp2 = DBSession.get(WikiPage, wp._id) # wp2 lookup won’t query the database again
  • 9. How Validation works ● Ming documents are validated at certain points in their life cycle ○ When saving the document to the database ○ When loading it from the database. ○ Additionally, validation is performed when the document is created through the ODM layer or using the .make() method ■ Happens before they get saved for real
  • 10. Cost of Validation ● MongoDB is famous for its speed, but validation has a cost ○ MongoDB documents can contain many subdocuments ○ Each subdocument must be validated by ming ○ Can even contain lists of multiple subdocuments
  • 11. Cost of Validation benchmark #With Validation class User(MappedClass): # ... friends = FieldProperty([dict(fbuser=s.String, photo=s.String, name=s.String)], if_missing=[]) >>> timeit.timeit('User.query.find().all()', number=20000) 31.97218942642212 #Without Validation class User(MappedClass): # ... friends = FieldProperty(s.Anything, if_missing=[]) >>> timeit.timeit('User.query.find().all()', number=20000) 23.391359090805054 #Avoiding the field at query time >>> timeit.timeit('User.query.find({}, fields=("_id","name")).all()', number=20000) 21.58667516708374
  • 12. Only query what you need ● Previous benchmark explains why it is good to query only for fields you need to process the current request ● All the fields you don’t query for, will still be available in the object with None value
  • 13. Evolving the Schema ● Migrations are performed lazily as the objects are loaded from the database ● Simple schema evolutions: ○ New field: It will just be None for old entities. ○ Removed: Declare it as ming.schema.Deprecated ○ Changed Type: Declare it as ming.schema.Migrate ● Complex schema evolutions: ○ Add a migration function in __mongometa__
  • 14. Complex migrations with Ming class OldWikiPage(Document): _id = Field(schema.ObjectId) title = Field(str) text = Field(str, if_missing='') metadata = Field(dict(tags=[str], categories=[str])) class WikiPage(Document): class __mongometa__: session = DBSession name = 'wiki_page' version_of = OldWikiPage def migrate(data): result = dict(data, version=1, tags=data['metadata']['tags'], categories=data['metadata']['categories']) del result['metadata'] return result version = Field(1, required=True) # … more fields ...
  • 15. Testing MongoDB ● Ming makes testing easy ○ Your models can be directly imported from tests ○ Just bind the session to a DataStorage created in your tests suite ● Ming provides MongoInMemory ○ much like sqlite://:memory: ● Implements 90% of mongodb, including javascript execution with spidermonkey
  • 16. Ming for Web Applications ● Ming can be integrated in any WSGI framework through the ming.odm. middleware.MingMiddleware ○ Automatically disposes open sessions at the end of requests ○ Automatically provides session flushing ○ Automatically clears the session in case of exceptions
  • 17. Ming with TurboGears ● Provides builtin support for ming ○ $ gearbox quickstart --ming projectname ● Ready made test suite with fixtures on MIM ● Facilities to debug and benchmark Ming queries through the DebugBar ● TurboGears Admin automatically generates CRUD from Ming models
  • 18. Debugging MongoDB ● TurboGears debugbar has builtin support for MongoDB ○ Executed queries logging and results ○ Queries timing ○ Syntax prettifier and highlight for Map-Reduce and $where javascript code ○ Queries tracking on logs for performance reporting of webservices
  • 20. Ming without learning MongoDB ● Transition from SQL/Relational solutions to MongoDB can be scary first time. ● You can use Sprox to lower the learning cost for simple applications ○ Sprox is the library that empowers TurboGears Admin to automatically generate pages from SQLA or Ming
  • 21. Sprox ORM abstractions ● ORMProvider, provides an abstraction over the ORM ● ORMProviderSelector, automatically detects the provider to use from a model. ● Mix those together and you have a db independent layer with automatic storage backend detection.
  • 22. Hands on Sprox ● Provider.query(self, entity, **kwargs) → get all objects of a collection ● Provider.get_obj(self, entity, params) → get an object ● Provider.update(self, entity, params) → update an object ● Provider.create(self, entity, params) → create a new object # Sprox (Ming or SQLAlchemy) count, transactions = provider.query(MoneyTransfer) transactions = DBSession.query(MoneyTransfer).all() # SQLAlchemy transactions = MoneyTransfer.query.find().all() # Ming