Skip to content

Commit

Permalink
datastore: scope Key creation to include NS. fixes #116.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenplusplus committed Aug 20, 2014
1 parent 6207a6d commit f9f98a3
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 111 deletions.
39 changes: 14 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ TODO
Get operations require a valid key to retrieve the key identified entity from Datastore. Skip to the "Querying" section if you'd like to learn more about querying against Datastore.

~~~~ js
ds.get(datastore.key('Company', 123), function(err, entity) {});
ds.get(ds.key('Company', 123), function(err, entity) {});

// alternatively, you can retrieve multiple entities at once.
ds.get([
datastore.key('Company', 123),
datastore.key('Product', 'Computer')
ds.key('Company', 123),
ds.key('Product', 'Computer')
], function(err, entities) {});
~~~~

Expand All @@ -114,15 +114,15 @@ To learn more about keys and incomplete keys, skip to the Keys section.

~~~~ js
ds.save({
key: datastore.key('Company', null), data: {/*...*/}
key: ds.key('Company', null), data: {/*...*/}
}, function(err, key) {
// First arg is an incomplete key for Company kind.
// console.log(key) will output ['Company', 599900452312].
});
// alternatively, you can save multiple entities at once.
ds.save([
{ key: datastore.key('Company', 123), data: {/*...*/} },
{ key: datastore.key('Product', 'Computer'), data: {/*...*/} }
{ key: ds.key('Company', 123), data: {/*...*/} },
{ key: ds.key('Product', 'Computer'), data: {/*...*/} }
], function(err, keys) {
// if the first key was incomplete, keys[0] will return the generated key.
});
Expand All @@ -136,10 +136,10 @@ ds.delete(['Company', 599900452312], function(err) {});
// alternatively, you can delete multiple entities of different
// kinds at once.
ds.delete([
datastore.key('Company', 599900452312),
datastore.key('Company', 599900452315),
datastore.key('Office', 'mtv'),
datastore.key('Company', 123, 'Employee', 'jbd')
ds.key('Company', 599900452312),
ds.key('Company', 599900452315),
ds.key('Office', 'mtv'),
ds.key('Company', 123, 'Employee', 'jbd')
], function(err) {});
~~~~

Expand Down Expand Up @@ -178,14 +178,14 @@ stored as properties is not currently supported.

~~~~ js
var q = ds.createQuery('Company')
.filter('__key__ =', datastore.key('Company', 'Google'))
.filter('__key__ =', ds.key('Company', 'Google'))
~~~~

In order to filter by ancestors, use `hasAncestor` helper.

~~~ js
var q = ds.createQuery('Child')
.hasAncestor(datastore.key('Parent', 123));
.hasAncestor(ds.key('Parent', 123));
~~~

##### Sorting
Expand Down Expand Up @@ -223,25 +223,14 @@ var q = ds.createQuery('Company')
#### Allocating IDs (ID generation)

You can generate IDs without creating entities. The following call will create
100 new IDs from the Company kind which exists under the default namespace.
100 new IDs from the Company kind which exists under the dataset's namespace.

~~~~ js
ds.allocateIds(datastore.key('Company', null), 100, function(err, keys) {
ds.allocateIds(ds.key('Company', null), 100, function(err, keys) {

});
~~~~

You may prefer to create IDs from a non-default namespace by providing
an incomplete key with a namespace. Similar to the previous example, the
call below will create 100 new IDs, but from the Company kind that exists
under the "ns-test" namespace.

~~~~ js
var incompleteKey = datastore.key('ns-test', 'Company', null);
ds.allocateIds(incompleteKey, 100, function(err, keys) {
});
~~~~

#### Transactions

Datastore has support for transactions. Transactions allow you to perform
Expand Down
35 changes: 26 additions & 9 deletions lib/datastore/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,32 +54,49 @@ var SCOPES = [
* @constructor
* @alias module:datastore/dataset
*
* @param {object} options
* @param {string} options.id - Dataset ID. This is your project ID from the
* Google Developers Console.
* @param {object=} options
* @param {string} options.projectId - Dataset ID. This is your project ID from
* the Google Developers Console.
* @param {string} options.keyFileName - Full path to the JSON key downloaded
* from the Google Developers Console.
* @param {string} options.namespace - Namespace to isolate transactions to.
*
* @example
* ```js
* var dataset = new Dataset({
* id: 'my-project',
* projectId: 'my-project',
* keyFileName: '/path/to/keyfile.json'
* });
* ```
*/
function Dataset(opts) {
opts = opts || {};
var id = opts.projectId;
function Dataset(options) {
options = options || {};

this.connection = new conn.Connection({
keyFilename: opts.keyFilename,
keyFilename: options.keyFilename,
scopes: SCOPES
});
this.id = id;
this.id = options.projectId;
this.ns = options.namespace;
this.transaction = this.createTransaction_();
}

/**
* Helper to create a Key object, scoped to the namespace if present.
*
* @example
* ```js
* var key = dataset.key('Company', 123);
* ```
*/
Dataset.prototype.key = function() {
return new entity.Key({
namespace: this.ns,
path: [].slice.call(arguments)
});
};


/**
* Create a query from the current dataset to query the specified kinds.
*
Expand Down
39 changes: 19 additions & 20 deletions lib/datastore/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,22 @@ var SIGN_TO_ORDER = {
* Build a Datastore Key object.
*
* @constructor
* @param {...*} - Key descriptors.
* @param {object} - Configuration object.
* @param {...*} options.path - Key path.
* @param {string=} options.namespace - Optional namespace.
*
* @example
* ```js
* var key = new Key('Company', 123);
* ```
*/
function Key() {
if (arguments.length > 1) {
this.path_ = [].slice.call(arguments);
function Key(options) {
this.namespace_ = options.namespace;

if (options.path.length > 1) {
this.path_ = [].slice.call(options.path);
} else {
this.path_ = arguments[0];
this.path_ = options.path[0];
}
}

Expand Down Expand Up @@ -220,15 +224,17 @@ module.exports.entityFromEntityProto = entityFromEntityProto;
* ```
*/
function keyFromKeyProto(proto) {
var keyPath = [];
var keyOptions = {
path: []
};
if (proto.partition_id && proto.partition_id.namespace) {
keyPath.push(proto.partition_id.namespace);
keyOptions.namespace = proto.partition_id.namespace;
}
proto.path_element.forEach(function(path) {
keyPath.push(path.kind);
keyPath.push(Number(path.id) || path.name || null);
keyOptions.path.push(path.kind);
keyOptions.path.push(Number(path.id) || path.name || null);
});
return new Key(keyPath);
return new Key(keyOptions);
}

module.exports.keyFromKeyProto = keyFromKeyProto;
Expand Down Expand Up @@ -261,15 +267,8 @@ function keyToKeyProto(key) {
if (keyPath.length < 2) {
throw new Error('A key should contain at least a kind and an identifier.');
}
var namespace = null;
var start = 0;
if (keyPath.length % 2 === 1) {
// the first item is the namespace
namespace = keyPath[0];
start = 1;
}
var path = [];
for (var i = start; i < (keyPath.length - start); i += 2) {
for (var i = 0; i < keyPath.length; i += 2) {
var p = { kind: keyPath[i] };
var val = keyPath[i+1];
if (val) {
Expand All @@ -285,9 +284,9 @@ function keyToKeyProto(key) {
var proto = {
path_element: path
};
if (namespace) {
if (key.namespace_) {
proto.partition_id = {
namespace: namespace
namespace: key.namespace_
};
}
return proto;
Expand Down
12 changes: 0 additions & 12 deletions lib/datastore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ var datastore = {};
*/
datastore.Dataset = require('./dataset');

/**
* @borrows {module:datastore/entity~Key} as key
*
* @example
* ```js
* var key = dataset.key('Company', 123);
* ```
*/
datastore.key = function() {
return new entity.Key([].slice.call(arguments));
};

/**
* @borrows {module:datastore/entity~Int} as int
*
Expand Down
42 changes: 21 additions & 21 deletions regression/datastore.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var entity = require('../lib/datastore/entity.js');
describe('datastore', function() {

it('should allocate IDs', function(done) {
ds.allocateIds(datastore.key('Kind', null), 10, function(err, keys) {
ds.allocateIds(ds.key('Kind', null), 10, function(err, keys) {
assert.ifError(err);
assert.equal(keys.length, 10);
assert.equal(entity.isKeyComplete(keys[0]), true);
Expand All @@ -48,7 +48,7 @@ describe('datastore', function() {
};

it('should save/get/delete with a key name', function(done) {
var postKey = datastore.key('Post', 'post1');
var postKey = ds.key('Post', 'post1');
ds.save({ key: postKey, data: post }, function(err, key) {
assert.ifError(err);
assert.equal(key.path_[1], 'post1');
Expand All @@ -64,7 +64,7 @@ describe('datastore', function() {
});

it('should save/get/delete with a numeric key id', function(done) {
var postKey = datastore.key('Post', 123456789);
var postKey = ds.key('Post', 123456789);
ds.save({
key: postKey,
data: post
Expand All @@ -84,16 +84,16 @@ describe('datastore', function() {

it('should save/get/delete with a generated key id', function(done) {
ds.save({
key: datastore.key('Post', null),
key: ds.key('Post', null),
data: post
}, function(err, key) {
assert.ifError(err);
var assignedId = key.path_[1];
assert(assignedId);
ds.get(datastore.key('Post', assignedId), function(err, entity) {
ds.get(ds.key('Post', assignedId), function(err, entity) {
assert.ifError(err);
assert.deepEqual(entity.data, post);
ds.delete(datastore.key('Post', assignedId), function(err) {
ds.delete(ds.key('Post', assignedId), function(err) {
assert.ifError(err);
done();
});
Expand All @@ -111,15 +111,15 @@ describe('datastore', function() {
wordCount: 450,
rating: 4.5,
};
var key = datastore.key('Post', null);
var key = ds.key('Post', null);
ds.save([
{ key: key, data: post },
{ key: key, data: post2 }
], function(err, keys) {
assert.ifError(err);
assert.equal(keys.length,2);
var firstKey = datastore.key('Post', keys[0].path_[1]);
var secondKey = datastore.key('Post', keys[1].path_[1]);
var firstKey = ds.key('Post', keys[0].path_[1]);
var secondKey = ds.key('Post', keys[1].path_[1]);
ds.get([firstKey, secondKey], function(err, entities) {
assert.ifError(err);
assert.equal(entities.length, 2);
Expand All @@ -135,7 +135,7 @@ describe('datastore', function() {

it('should be able to save keys as a part of entity and query by key',
function(done) {
var personKey = datastore.key('Person', 'name');
var personKey = ds.key('Person', 'name');
ds.save({
key: personKey,
data: {
Expand All @@ -158,14 +158,14 @@ describe('datastore', function() {
describe('querying the datastore', function() {

var keys = [
datastore.key('Character', 'Rickard'),
datastore.key('Character', 'Rickard', 'Character', 'Eddard'),
datastore.key('Character', 'Catelyn'),
datastore.key('Character', 'Eddard', 'Character', 'Arya'),
datastore.key('Character', 'Eddard', 'Character', 'Sansa'),
datastore.key('Character', 'Eddard', 'Character', 'Robb'),
datastore.key('Character', 'Eddard', 'Character', 'Bran'),
datastore.key('Character', 'Eddard', 'Character', 'Jon Snow')
ds.key('Character', 'Rickard'),
ds.key('Character', 'Rickard', 'Character', 'Eddard'),
ds.key('Character', 'Catelyn'),
ds.key('Character', 'Eddard', 'Character', 'Arya'),
ds.key('Character', 'Eddard', 'Character', 'Sansa'),
ds.key('Character', 'Eddard', 'Character', 'Robb'),
ds.key('Character', 'Eddard', 'Character', 'Bran'),
ds.key('Character', 'Eddard', 'Character', 'Jon Snow')
];

var characters = [{
Expand Down Expand Up @@ -265,7 +265,7 @@ describe('datastore', function() {

it('should filter by ancestor', function(done) {
var q = ds.createQuery('Character')
.hasAncestor(datastore.key('Character', 'Eddard'));
.hasAncestor(ds.key('Character', 'Eddard'));
ds.runQuery(q, function(err, entities) {
assert.ifError(err);
assert.equal(entities.length, 5);
Expand All @@ -275,7 +275,7 @@ describe('datastore', function() {

it('should filter by key', function(done) {
var q = ds.createQuery('Character')
.filter('__key__ =', datastore.key('Character', 'Rickard'));
.filter('__key__ =', ds.key('Character', 'Rickard'));
ds.runQuery(q, function(err, entities) {
assert.ifError(err);
assert.equal(entities.length, 1);
Expand Down Expand Up @@ -370,7 +370,7 @@ describe('datastore', function() {
describe('transactions', function() {

it('should run in a transaction', function(done) {
var key = datastore.key('Company', 'Google');
var key = ds.key('Company', 'Google');
var obj = {
url: 'www.google.com'
};
Expand Down
Loading

0 comments on commit f9f98a3

Please sign in to comment.