RESTful Web APIs
and MongoDB go for a picnic
Nicola Iarocci @nicolaiarocci
Nicola Iarocci
Eve REST API Framework, Cerberus, Events
Co-founder @ [Link],
Book Author,
MongoDB Master
Nicola Iarocci
TL;DR
Passionate full stack developer
Il Piccolo
Libro di MongoDB
edizione italiana del libro di Karl Seguin
disponibile per il download @ [Link]
[Link]
invoicing & accounting
[Link]
your typical old school desktop application
[Link]
now going web and mobile
[Link]
“ we need a remote API to keep everything in sync ”
e nt
A -ha mo m
Before
Client Database
Desktop!
Application LAN/SQL
Initial draft
Clients API Database
iOS
Android
RESTful !
“Cloud”
Website Web API
Desktop Client
? ?
Constraints
• minimum viable product first
• add features over time
• frequent database schema updates
• avoid downtime as much as possible
So we started
exploring new paths
MongoDB and REST
!
or why we picked MongoDB for our REST API
JSON-style data store
true selling point for me
JSON for transport
all client to API communication is going to be JSON
JSON & RESTful API
GET
Client Mongo
JSON! JSON!
accepted media type (BSON)
maybe we can push directly to client?
JSON & RESTful API
GET
Client API Mongo
JSON! JSON! JSON!
accepted media type subset of python dict! (BSON)
(kinda)
almost.
JSON & RESTful API
POST
Client API Mongo
JSON! JSON/dict! JSON!
maps to python dict!
objects (BSON)
(validation layer)
also works when posting (adding) items to the database
Similarity with
RDBMS
made NoSQL easy to grasp (even for a dumbhead like me)
Terminology
RDBMS Mongo
Database Database
Table Collection
Rows(s) JSON Document
Index Index
Join Embedding & Linking
What about Queries?
Queries in MongoDB are represented as JSON-style objects
// select * from things where x=3 and y="foo"
[Link]({x: 3, y: "foo”});
Filtering and Sorting
let’s simply expose MongoDB syntax
?where={x: 3, y: "foo”}
Client API Mongo
(very) thin
native! parsing! JSON!
Mongo! & validation (BSON)
query syntax
layer
JSON
all along the pipeline
mapping to and from the database feels more natural
ORM
Where we’re going we don’t need ORMs.
Schema-less
dynamic documents allow for painless, progressive evolution
PyMongo
MongoDB drivers are beautiful. Really.
Also in MongoDB
• setup is a breeze
• lightweight
• fast inserts, updates and queries
• excellent documentation
• great support by 10gen
• great community
REST in practice
!
with some MongoDB love
Collections
API entry point + plural nouns
[Link]/contacts
M o n go c ol l e c ti o n
Maps t o a
Document
API entry point + plural nouns + ID
[Link]/contacts/4f46445fc88e201858000000
l e c t io n O b j ec t I D
Maps t o a c o l
GET
Retrieving Resoruce Data
Resource GET
/contacts?where={“age”: {“$gt”: 20}}&projection={“lastname”: 1}
def get_collection(collection):!
documents = []!
cursor = db(collection).find(where, projection)!
for document in cursor:!
[Link](document)!
return documents
find() accepts a python dict
as query expression, and
returns a cursor we can
iterate
Resource GET
/contacts?where={“age”: {“$gt”: 20}}&projection={“lastname”: 1}
def get_collection(collection):!
documents = []!
cursor = db(collection).find(where, projection)!
for document in cursor:!
[Link](document)!
return documents
find() accepts a python dict
as query expression, and
returns a cursor we can
iterate
Resource GET
/contacts?where={“age”: {“$gt”: 20}}&projection={“lastname”: 1}
def get_collection(collection):!
documents = []!
cursor = db(collection).find(where, projection)!
for document in cursor:!
[Link](document)!
return documents
find() accepts a python dict
as query expression, and
returns a cursor we can
iterate
JSON Rendering
JSON Rendering
f r o m Mo n go
straight
JSON Rendering
PATCH
Editing a Document
PATCHing
def patch_document(collection, original):!
(...)!
# Perform the update!
db(collection).update({"_Id": ObjectId(object_id)}, !
{"$set": updates})!
mongo update() method
commits updates to the
database.
PATCHing
def patch_document(collection, original):!
(...)!
# Perform the update!
db(collection).update({"_Id": ObjectId(object_id)}, !
{"$set": updates})!
udpate() takes the unique Id
of the document to update
PATCHing
def patch_document(collection, original):!
(...)!
# Perform the update!
db(collection).update({"_Id": ObjectId(object_id)}, !
{"$set": updates})!
$set accepts a dict!
with the updates for the db
eg: {“active”: False}.
updates are atomic
POST
Creating Resources
POSTing
Take #1
def post(collection):!
(...)!
for key, item in [Link]():!
response[ID_FIELD] = db(collection).insert(item)
push document and get its
ObjectId back from Mongo.
like other CRUD operations,
inserting is trivial in
mongo.
POSTing
Take #2
Bulk inserts!!
(let’s look at the code)
after a lot of tinkering
we released an ambitious open source project
Eve
REST API Framework powered by
Flask, MongoDB and good intentions
[Link]
Beta 0.2
• 1.000+ stargazers • 24 contributors
• 120 forks • 7.935 downloads
Eve Extensions
contributed by the community
• Eve-ElasticSearch
• Eve-SQLAlchemy
• Eve-Docs
• Eve-Mocks
Wanna see it running?
Hopefully it won’t explode right into my face
Initial draft
Clients API Database
iOS
Android
RESTful !
“Cloud”
Website Web API
Desktop Client
? ?
Production
Clients API Database
iOS
Android
Adam! MongoDB
Website eve instance
Desktop Client
MongoDB Rocks!
your RESTful Web API
Thank you.
nicolaiarocci