Skip to content

Commit f9f98a3

Browse files
datastore: scope Key creation to include NS. fixes googleapis#116.
1 parent 6207a6d commit f9f98a3

File tree

7 files changed

+130
-111
lines changed

7 files changed

+130
-111
lines changed

README.md

+14-25
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ TODO
9999
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.
100100

101101
~~~~ js
102-
ds.get(datastore.key('Company', 123), function(err, entity) {});
102+
ds.get(ds.key('Company', 123), function(err, entity) {});
103103

104104
// alternatively, you can retrieve multiple entities at once.
105105
ds.get([
106-
datastore.key('Company', 123),
107-
datastore.key('Product', 'Computer')
106+
ds.key('Company', 123),
107+
ds.key('Product', 'Computer')
108108
], function(err, entities) {});
109109
~~~~
110110

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

115115
~~~~ js
116116
ds.save({
117-
key: datastore.key('Company', null), data: {/*...*/}
117+
key: ds.key('Company', null), data: {/*...*/}
118118
}, function(err, key) {
119119
// First arg is an incomplete key for Company kind.
120120
// console.log(key) will output ['Company', 599900452312].
121121
});
122122
// alternatively, you can save multiple entities at once.
123123
ds.save([
124-
{ key: datastore.key('Company', 123), data: {/*...*/} },
125-
{ key: datastore.key('Product', 'Computer'), data: {/*...*/} }
124+
{ key: ds.key('Company', 123), data: {/*...*/} },
125+
{ key: ds.key('Product', 'Computer'), data: {/*...*/} }
126126
], function(err, keys) {
127127
// if the first key was incomplete, keys[0] will return the generated key.
128128
});
@@ -136,10 +136,10 @@ ds.delete(['Company', 599900452312], function(err) {});
136136
// alternatively, you can delete multiple entities of different
137137
// kinds at once.
138138
ds.delete([
139-
datastore.key('Company', 599900452312),
140-
datastore.key('Company', 599900452315),
141-
datastore.key('Office', 'mtv'),
142-
datastore.key('Company', 123, 'Employee', 'jbd')
139+
ds.key('Company', 599900452312),
140+
ds.key('Company', 599900452315),
141+
ds.key('Office', 'mtv'),
142+
ds.key('Company', 123, 'Employee', 'jbd')
143143
], function(err) {});
144144
~~~~
145145

@@ -178,14 +178,14 @@ stored as properties is not currently supported.
178178

179179
~~~~ js
180180
var q = ds.createQuery('Company')
181-
.filter('__key__ =', datastore.key('Company', 'Google'))
181+
.filter('__key__ =', ds.key('Company', 'Google'))
182182
~~~~
183183

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

186186
~~~ js
187187
var q = ds.createQuery('Child')
188-
.hasAncestor(datastore.key('Parent', 123));
188+
.hasAncestor(ds.key('Parent', 123));
189189
~~~
190190

191191
##### Sorting
@@ -223,25 +223,14 @@ var q = ds.createQuery('Company')
223223
#### Allocating IDs (ID generation)
224224

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

228228
~~~~ js
229-
ds.allocateIds(datastore.key('Company', null), 100, function(err, keys) {
229+
ds.allocateIds(ds.key('Company', null), 100, function(err, keys) {
230230

231231
});
232232
~~~~
233233

234-
You may prefer to create IDs from a non-default namespace by providing
235-
an incomplete key with a namespace. Similar to the previous example, the
236-
call below will create 100 new IDs, but from the Company kind that exists
237-
under the "ns-test" namespace.
238-
239-
~~~~ js
240-
var incompleteKey = datastore.key('ns-test', 'Company', null);
241-
ds.allocateIds(incompleteKey, 100, function(err, keys) {
242-
});
243-
~~~~
244-
245234
#### Transactions
246235

247236
Datastore has support for transactions. Transactions allow you to perform

lib/datastore/dataset.js

+26-9
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,49 @@ var SCOPES = [
5454
* @constructor
5555
* @alias module:datastore/dataset
5656
*
57-
* @param {object} options
58-
* @param {string} options.id - Dataset ID. This is your project ID from the
59-
* Google Developers Console.
57+
* @param {object=} options
58+
* @param {string} options.projectId - Dataset ID. This is your project ID from
59+
* the Google Developers Console.
6060
* @param {string} options.keyFileName - Full path to the JSON key downloaded
6161
* from the Google Developers Console.
62+
* @param {string} options.namespace - Namespace to isolate transactions to.
6263
*
6364
* @example
6465
* ```js
6566
* var dataset = new Dataset({
66-
* id: 'my-project',
67+
* projectId: 'my-project',
6768
* keyFileName: '/path/to/keyfile.json'
6869
* });
6970
* ```
7071
*/
71-
function Dataset(opts) {
72-
opts = opts || {};
73-
var id = opts.projectId;
72+
function Dataset(options) {
73+
options = options || {};
7474

7575
this.connection = new conn.Connection({
76-
keyFilename: opts.keyFilename,
76+
keyFilename: options.keyFilename,
7777
scopes: SCOPES
7878
});
79-
this.id = id;
79+
this.id = options.projectId;
80+
this.ns = options.namespace;
8081
this.transaction = this.createTransaction_();
8182
}
8283

84+
/**
85+
* Helper to create a Key object, scoped to the namespace if present.
86+
*
87+
* @example
88+
* ```js
89+
* var key = dataset.key('Company', 123);
90+
* ```
91+
*/
92+
Dataset.prototype.key = function() {
93+
return new entity.Key({
94+
namespace: this.ns,
95+
path: [].slice.call(arguments)
96+
});
97+
};
98+
99+
83100
/**
84101
* Create a query from the current dataset to query the specified kinds.
85102
*

lib/datastore/entity.js

+19-20
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,22 @@ var SIGN_TO_ORDER = {
8989
* Build a Datastore Key object.
9090
*
9191
* @constructor
92-
* @param {...*} - Key descriptors.
92+
* @param {object} - Configuration object.
93+
* @param {...*} options.path - Key path.
94+
* @param {string=} options.namespace - Optional namespace.
9395
*
9496
* @example
9597
* ```js
9698
* var key = new Key('Company', 123);
9799
* ```
98100
*/
99-
function Key() {
100-
if (arguments.length > 1) {
101-
this.path_ = [].slice.call(arguments);
101+
function Key(options) {
102+
this.namespace_ = options.namespace;
103+
104+
if (options.path.length > 1) {
105+
this.path_ = [].slice.call(options.path);
102106
} else {
103-
this.path_ = arguments[0];
107+
this.path_ = options.path[0];
104108
}
105109
}
106110

@@ -220,15 +224,17 @@ module.exports.entityFromEntityProto = entityFromEntityProto;
220224
* ```
221225
*/
222226
function keyFromKeyProto(proto) {
223-
var keyPath = [];
227+
var keyOptions = {
228+
path: []
229+
};
224230
if (proto.partition_id && proto.partition_id.namespace) {
225-
keyPath.push(proto.partition_id.namespace);
231+
keyOptions.namespace = proto.partition_id.namespace;
226232
}
227233
proto.path_element.forEach(function(path) {
228-
keyPath.push(path.kind);
229-
keyPath.push(Number(path.id) || path.name || null);
234+
keyOptions.path.push(path.kind);
235+
keyOptions.path.push(Number(path.id) || path.name || null);
230236
});
231-
return new Key(keyPath);
237+
return new Key(keyOptions);
232238
}
233239

234240
module.exports.keyFromKeyProto = keyFromKeyProto;
@@ -261,15 +267,8 @@ function keyToKeyProto(key) {
261267
if (keyPath.length < 2) {
262268
throw new Error('A key should contain at least a kind and an identifier.');
263269
}
264-
var namespace = null;
265-
var start = 0;
266-
if (keyPath.length % 2 === 1) {
267-
// the first item is the namespace
268-
namespace = keyPath[0];
269-
start = 1;
270-
}
271270
var path = [];
272-
for (var i = start; i < (keyPath.length - start); i += 2) {
271+
for (var i = 0; i < keyPath.length; i += 2) {
273272
var p = { kind: keyPath[i] };
274273
var val = keyPath[i+1];
275274
if (val) {
@@ -285,9 +284,9 @@ function keyToKeyProto(key) {
285284
var proto = {
286285
path_element: path
287286
};
288-
if (namespace) {
287+
if (key.namespace_) {
289288
proto.partition_id = {
290-
namespace: namespace
289+
namespace: key.namespace_
291290
};
292291
}
293292
return proto;

lib/datastore/index.js

-12
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,6 @@ var datastore = {};
3636
*/
3737
datastore.Dataset = require('./dataset');
3838

39-
/**
40-
* @borrows {module:datastore/entity~Key} as key
41-
*
42-
* @example
43-
* ```js
44-
* var key = dataset.key('Company', 123);
45-
* ```
46-
*/
47-
datastore.key = function() {
48-
return new entity.Key([].slice.call(arguments));
49-
};
50-
5139
/**
5240
* @borrows {module:datastore/entity~Int} as int
5341
*

regression/datastore.js

+21-21
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var entity = require('../lib/datastore/entity.js');
2828
describe('datastore', function() {
2929

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

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

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

8585
it('should save/get/delete with a generated key id', function(done) {
8686
ds.save({
87-
key: datastore.key('Post', null),
87+
key: ds.key('Post', null),
8888
data: post
8989
}, function(err, key) {
9090
assert.ifError(err);
9191
var assignedId = key.path_[1];
9292
assert(assignedId);
93-
ds.get(datastore.key('Post', assignedId), function(err, entity) {
93+
ds.get(ds.key('Post', assignedId), function(err, entity) {
9494
assert.ifError(err);
9595
assert.deepEqual(entity.data, post);
96-
ds.delete(datastore.key('Post', assignedId), function(err) {
96+
ds.delete(ds.key('Post', assignedId), function(err) {
9797
assert.ifError(err);
9898
done();
9999
});
@@ -111,15 +111,15 @@ describe('datastore', function() {
111111
wordCount: 450,
112112
rating: 4.5,
113113
};
114-
var key = datastore.key('Post', null);
114+
var key = ds.key('Post', null);
115115
ds.save([
116116
{ key: key, data: post },
117117
{ key: key, data: post2 }
118118
], function(err, keys) {
119119
assert.ifError(err);
120120
assert.equal(keys.length,2);
121-
var firstKey = datastore.key('Post', keys[0].path_[1]);
122-
var secondKey = datastore.key('Post', keys[1].path_[1]);
121+
var firstKey = ds.key('Post', keys[0].path_[1]);
122+
var secondKey = ds.key('Post', keys[1].path_[1]);
123123
ds.get([firstKey, secondKey], function(err, entities) {
124124
assert.ifError(err);
125125
assert.equal(entities.length, 2);
@@ -135,7 +135,7 @@ describe('datastore', function() {
135135

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

160160
var keys = [
161-
datastore.key('Character', 'Rickard'),
162-
datastore.key('Character', 'Rickard', 'Character', 'Eddard'),
163-
datastore.key('Character', 'Catelyn'),
164-
datastore.key('Character', 'Eddard', 'Character', 'Arya'),
165-
datastore.key('Character', 'Eddard', 'Character', 'Sansa'),
166-
datastore.key('Character', 'Eddard', 'Character', 'Robb'),
167-
datastore.key('Character', 'Eddard', 'Character', 'Bran'),
168-
datastore.key('Character', 'Eddard', 'Character', 'Jon Snow')
161+
ds.key('Character', 'Rickard'),
162+
ds.key('Character', 'Rickard', 'Character', 'Eddard'),
163+
ds.key('Character', 'Catelyn'),
164+
ds.key('Character', 'Eddard', 'Character', 'Arya'),
165+
ds.key('Character', 'Eddard', 'Character', 'Sansa'),
166+
ds.key('Character', 'Eddard', 'Character', 'Robb'),
167+
ds.key('Character', 'Eddard', 'Character', 'Bran'),
168+
ds.key('Character', 'Eddard', 'Character', 'Jon Snow')
169169
];
170170

171171
var characters = [{
@@ -265,7 +265,7 @@ describe('datastore', function() {
265265

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

276276
it('should filter by key', function(done) {
277277
var q = ds.createQuery('Character')
278-
.filter('__key__ =', datastore.key('Character', 'Rickard'));
278+
.filter('__key__ =', ds.key('Character', 'Rickard'));
279279
ds.runQuery(q, function(err, entities) {
280280
assert.ifError(err);
281281
assert.equal(entities.length, 1);
@@ -370,7 +370,7 @@ describe('datastore', function() {
370370
describe('transactions', function() {
371371

372372
it('should run in a transaction', function(done) {
373-
var key = datastore.key('Company', 'Google');
373+
var key = ds.key('Company', 'Google');
374374
var obj = {
375375
url: 'www.google.com'
376376
};

0 commit comments

Comments
 (0)