Introducing μDatastore, an ODM for Google Cloud Datastore

ML2Grow releases an open source Object-Document Mapper framework for use with the Google Cloud Datastore.

profile picture

Anton Van Moere

21 Nov 2018

illustration

In order to keep your code easily maintainable it is important to avoid duplication. Code duplication used to be the norm when working with databases. Your database needs to know which data types are used in your table and you need an internal object that you can manipulate inside your web app for example. Additional code is needed to convert between these two representations.

Object-Document Mappers (ODM’s) allow us to have a single representation to write and maintain.
The object and schema representations are then automatically derived by the ODM Framework.

Google Cloud Datastore

The ndb framework is very popular for interacting with datastore, but currently is only available on the Google App Engine standard runtime. It has not yet been ported for use in Python applications running elsewhere, despite being requested several times.
So we set out to make our own. We extended upon μMongo’s API to create a consistent experience throughout our code base in which we also connect to a Mongo database.

Show me the code!

Install μDatastore:

pip install udatastore

Setup a datastore instance:

from datetime import datetime
from google.cloud import datastore
from udatastore import DataStoreInstance
from umongo import Document, fields, validate

db = datastore.Client(project="dummy", namespace='abcd')
instance = DataStoreInstance()
instance.init(db)

Make a class corresponding to an entity:

@instance.register
class User(Document):
    email = fields.EmailField(required=True, unique=True)
    birthday = fields.DateTimeField(validate=validate.Range(min=datetime(1900, 1, 1)))
    friends = fields.ListField(fields.ReferenceField("User"))

Add some users:

goku = User(email='goku@sayen.com', birthday=datetime(1984, 11, 20))
goku.commit()
vegeta = User(email='vegeta@over9000.com', friends=[goku])
vegeta.commit()

Do a query:

User.find_one({"email": 'goku@sayen.com'})
# <object Document __main__.User({'email': 'goku@sayen.com', 'id': 4474,
#                                 'friends': <object umongo.data_objects.List([])>,
#                                 'birthday': datetime.datetime(1984, 11, 20, 0, 0)})>

Why Open Source?

Open source projects were essential for the recent revolution in machine learning. They allowed researchers to rapidly improve upon recent developments and are imperative to build machine learning applications in the real world. At ML2Grow we make use of dozens of open source projects and by releasing this framework we want to give back to the community.