Datastore driver

This tutorial references the the cDataHandler and cEzyOauth2, both of which have been superseded by cDbAbstraction and cGoa which are easier to implement. If you'd rather work with those, the slides below show an example.

do something in 5 with gas-9-copy between databases with oauth2

do something in 5 with ga...een databases with oauth2

Background to implementation.

This driver has been tricky to implement. The Cloud Datastore calls itself "Google Cloud Datastore: A Fully Managed NoSQL Data Storage Service" and is normally used with Google App Engine using Python, Java, PHP or Go. There is no API for Google Apps Script, it is not normally used directly from a JavaScript client, and neither is it a database as 'we would know it'.

There is a JSON API, and along with the new concepts of entities , paths, ancestors and tricky indexing it's quite difficult to get started with. It does have a GQL query language which is SQL-ish, but you can only use it for querying (not updating). It is also only really able to handle objects that are flat, and complicated queries need to have indexes pre-setup - in other words you need to know what you'l ask before you ask.

Since this is a database abstraction driver, I don't need the full capabilities of DataStore since I only need those that are present in other databases in the sub-universe. I also need to use Flattening an object with dot syntax to allow for multi level object storage and querying, and because of the limitation around pre-indexing, I need to do hybrid querying with some of it happening in datastore, and more complex constraints happening in the DataHandler.

Here's a quick primer.

Quotas

Before you choose to use DataStore, you'll need to think about quotas. It's very easy to blow the free daily allowance - for any meaningful application you'll probably end up paying something. There is a quota dashboard on the Google Developers Cloud console.

The data abstraction library has caching enabled from the start, so any data taken from cache doesn't eat into your quota.

Locking

Although Datastore has the concept of 'Transactions', you can't protect sections of code like you can when you use it with App Engine. I'm Using named locks with Google Apps Scripts to protect sensitive transactions.

First time in, provoke a doGet() dialog by publishing as a web app to create an access and refresh token. This will grab an offline authorization which will refresh automatically when needed. These will be used for both web apps and non-webapps. However you do need to publish and run once to create the dialog. If this is a non-web app, then unpublish it again when done. Your doGet() function looks like this. If this is a web actually a webapp, then the doSomething() function is where you create your app.

More info

The datastore code

The datastore test.

If you've already used Database abstraction with google apps script then this will be familiar. The database access is the same for datastore as it is for any other backend. The only specific coding is setting up the handler. Here are 3 different setups for 3 different backends - datastore, parse.com and Drive. You'll notice they are very similar. In this i've opted out of analytics tracking, and turned off caching- since I'm going to run the same tests on each platform to make sure I get the same result. You'll find these tests in the Patterns template and you may find them useful to check out your set up.

function dataStoreTest (accessToken) {

// get a datastore handler

var handler = new cDataHandler.DataHandler (

'flattener', // Kind

cDataHandler.dhConstants.DB.DATASTORE, // Datastore

undefined,

'xliberationdatastore', // project id

undefined,

undefined,

true, // analytics opt out

'bruce', // analytics debugging tracking

accessToken, // the access token

true); // disable caching for testing

assert(handler.isHappy(), 'unable to get datastore handler','handler');

return testFlattener (handler, accessToken)

}

function driveTest (accessToken) {

// get a datastore handler

var handler = new cDataHandler.DataHandler (

'flattener.json', // Kind

cDataHandler.dhConstants.DB.DRIVE, // Datastore

undefined,

'/datahander/driverdrive', // project id

undefined,

undefined,

true, // analytics opt out

'bruce', // analytics debugging tracking

accessToken, // the access token

true); // disable caching for testing

assert(handler.isHappy(), 'unable to get drive handler','handler');

return testFlattener (handler, accessToken)

}

function parseTest () {

// get a parse handler

var userStore = PropertiesService.getScriptProperties();

var handler = new cDataHandler.DataHandler (

'flattener', // class

cDataHandler.dhConstants.DB.PARSE, // parse

undefined,

'mp',

JSON.parse(userStore.getProperty("parseKeys")), // parse credentials

undefined,

true,

'bruce',

undefined,

true);

assert(handler.isHappy(), 'unable to get parse handler','handler');

return testFlattener (handler,null)

}

Here's a set of tests - it doesn't matter which back end you are using. The code is the same.