Skip to content

Commit 182fd84

Browse files
committed
Updating Node.js SQL API sample to use partition key
1 parent 7d82ac4 commit 182fd84

File tree

1 file changed

+29
-254
lines changed

1 file changed

+29
-254
lines changed

articles/cosmos-db/sql-api-nodejs-get-started.md

Lines changed: 29 additions & 254 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ms.service: cosmos-db
66
ms.subservice: cosmosdb-sql
77
ms.devlang: nodejs
88
ms.topic: tutorial
9-
ms.date: 09/24/2018
9+
ms.date: 06/05/2019
1010
ms.author: dech
1111
Customer intent: As a developer, I want to build a Node.js console application to access and manage SQL API account resources in Azure Cosmos DB, so that customers can better use the service.
1212

@@ -91,93 +91,13 @@ Now that your app exists, you need to make sure it can talk to Azure Cosmos DB.
9191
config.primaryKey = "~your primary key here~";
9292
```
9393

94-
1. Copy and paste the ```database```, ```container```, and ```items``` data to your ```config``` object below where you set your ```config.endpoint``` and ```config.primaryKey``` properties. If you already have data you'd like to store in your database, you can use the Data Migration tool in Azure Cosmos DB rather than defining the data here.
94+
1. Copy and paste the ```database```, ```container```, and ```items``` data to your ```config``` object below where you set your ```config.endpoint``` and ```config.primaryKey``` properties. If you already have data you'd like to store in your database, you can use the Data Migration tool in Azure Cosmos DB rather than defining the data here. You config.js file should have the following code:
9595

96-
```javascript
97-
var config = {}
98-
99-
config.endpoint = "~your Azure Cosmos DB account endpoint uri here~";
100-
config.primaryKey = "~your primary key here~";
101-
102-
config.database = {
103-
"id": "FamilyDatabase"
104-
};
105-
106-
config.container = {
107-
"id": "FamilyContainer"
108-
};
109-
110-
config.items = {
111-
"Andersen": {
112-
"id": "Anderson.1",
113-
"lastName": "Andersen",
114-
"parents": [{
115-
"firstName": "Thomas"
116-
}, {
117-
"firstName": "Mary Kay"
118-
}],
119-
"children": [{
120-
"firstName": "Henriette Thaulow",
121-
"gender": "female",
122-
"grade": 5,
123-
"pets": [{
124-
"givenName": "Fluffy"
125-
}]
126-
}],
127-
"address": {
128-
"state": "WA",
129-
"county": "King",
130-
"city": "Seattle"
131-
}
132-
},
133-
"Wakefield": {
134-
"id": "Wakefield.7",
135-
"parents": [{
136-
"familyName": "Wakefield",
137-
"firstName": "Robin"
138-
}, {
139-
"familyName": "Miller",
140-
"firstName": "Ben"
141-
}],
142-
"children": [{
143-
"familyName": "Merriam",
144-
"firstName": "Jesse",
145-
"gender": "female",
146-
"grade": 8,
147-
"pets": [{
148-
"givenName": "Goofy"
149-
}, {
150-
"givenName": "Shadow"
151-
}]
152-
}, {
153-
"familyName": "Miller",
154-
"firstName": "Lisa",
155-
"gender": "female",
156-
"grade": 1
157-
}],
158-
"address": {
159-
"state": "NY",
160-
"county": "Manhattan",
161-
"city": "NY"
162-
},
163-
"isRegistered": false
164-
}
165-
};
166-
```
96+
[!code-javascript[nodejs-get-started](~/cosmosdb-nodejs-get-started/config.js)]
16797

16898
JavaScript SDK uses the generic terms *container* and *item*. A container can be a collection, graph, or table. An item can be a document, edge/vertex, or row, and is the content inside a container.
169-
170-
1. Finally, export your ```config``` object, so that you can reference it within the ```app.js``` file.
171-
172-
```javascript
173-
},
174-
"isRegistered": false
175-
}
176-
};
177-
178-
// ADD THIS PART TO YOUR CODE
179-
module.exports = config;
180-
```
99+
100+
`module.exports = config;` code isused to export your ```config``` object, so that you can reference it within the ```app.js``` file.
181101

182102
## <a id="Connect"></a>Connect to an Azure Cosmos DB account
183103

@@ -225,6 +145,7 @@ Now that you have the code to initialize the Azure Cosmos DB client, let's take
225145
226146
const databaseId = config.database.id;
227147
const containerId = config.container.id;
148+
const partitionKey = { kind: "Hash", paths: ["/Country"] };
228149
```
229150
230151
A database can be created by using either the `createIfNotExists` or create function of the **Databases** class. A database is the logical container of items partitioned across containers.
@@ -287,6 +208,7 @@ Now that you have the code to initialize the Azure Cosmos DB client, let's take
287208

288209
const databaseId = config.database.id;
289210
const containerId = config.container.id;
211+
const partitionKey = { kind: "Hash", paths: ["/Country"] };
290212

291213
/**
292214
* Create the database if it does not exist
@@ -343,17 +265,19 @@ A container can be created by using either the `createIfNotExists` or create fun
343265
/**
344266
* Create the container if it does not exist
345267
*/
268+
346269
async function createContainer() {
347-
const { container } = await client.database(databaseId).containers.createIfNotExists({ id: containerId });
270+
271+
const { container } = await client.database(databaseId).containers.createIfNotExists({ id: containerId, partitionKey }, { offerThroughput: 400 });
348272
console.log(`Created container:\n${config.container.id}\n`);
349273
}
350274

351275
/**
352-
* Read the container definition
276+
* Read the container definition
353277
*/
354278
async function readContainer() {
355-
const { body: containerDefinition } = await client.database(databaseId).container(containerId).read();
356-
console.log(`Reading container:\n${containerDefinition.id}\n`);
279+
const { body: containerDefinition } = await client.database(databaseId).container(containerId).read();
280+
console.log(`Reading container:\n${containerDefinition.id}\n`);
357281
}
358282
```
359283

@@ -388,6 +312,7 @@ A container can be created by using either the `createIfNotExists` or create fun
388312

389313
const databaseId = config.database.id;
390314
const containerId = config.container.id;
315+
const partitionKey = { kind: "Hash", paths: ["/Country"] };
391316

392317
/**
393318
* Create the database if it does not exist
@@ -408,17 +333,19 @@ A container can be created by using either the `createIfNotExists` or create fun
408333
/**
409334
* Create the container if it does not exist
410335
*/
336+
411337
async function createContainer() {
412-
const { container } = await client.database(databaseId).containers.createIfNotExists({ id: containerId });
413-
console.log(`Created container:\n${config.container.id}\n`);
338+
339+
const { container } = await client.database(databaseId).containers.createIfNotExists({ id: containerId, partitionKey }, { offerThroughput: 400 });
340+
console.log(`Created container:\n${config.container.id}\n`);
414341
}
415342

416343
/**
417-
* Read the container definition
344+
* Read the container definition
418345
*/
419346
async function readContainer() {
420-
const { body: containerDefinition } = await client.database(databaseId).container(containerId).read();
421-
console.log(`Reading container:\n${containerDefinition.id}\n`);
347+
const { body: containerDefinition } = await client.database(databaseId).container(containerId).read();
348+
console.log(`Reading container:\n${containerDefinition.id}\n`);
422349
}
423350

424351
/**
@@ -455,23 +382,11 @@ An item can be created by using the create function of the **Items** class. When
455382

456383
```javascript
457384
/**
458-
* Create family item if it does not exist
385+
* Create family item
459386
*/
460387
async function createFamilyItem(itemBody) {
461-
try {
462-
// read the item to see if it exists
463-
const { item } = await client.database(databaseId).container(containerId).item(itemBody.id).read();
464-
console.log(`Item with family id ${itemBody.id} already exists\n`);
465-
}
466-
catch (error) {
467-
// create the family item if it does not exist
468-
if (error.code === HttpStatusCodes.NOTFOUND) {
469-
const { item } = await client.database(databaseId).container(containerId).items.create(itemBody);
470-
console.log(`Created family item with id:\n${itemBody.id}\n`);
471-
} else {
472-
throw error;
473-
}
474-
}
388+
const { item } = await client.database(databaseId).container(containerId).items.upsert(itemBody);
389+
console.log(`Created family item with id:\n${itemBody.id}\n`);
475390
};
476391
```
477392

@@ -500,6 +415,7 @@ An item can be created by using the create function of the **Items** class. When
500415

501416

502417
## <a id="Query"></a>Query Azure Cosmos DB resources
418+
503419
Azure Cosmos DB supports rich queries against JSON documents stored in each container. The following sample code shows a query that you can run against the documents in your container.
504420

505421
1. Copy and paste the **queryContainer** function below the **createFamilyItem** function in the app.js file. Azure Cosmos DB supports SQL-like queries as shown below.
@@ -522,7 +438,7 @@ Azure Cosmos DB supports rich queries against JSON documents stored in each cont
522438
]
523439
};
524440

525-
const { result: results } = await client.database(databaseId).container(containerId).items.query(querySpec).toArray();
441+
const { result: results } = await client.database(databaseId).container(containerId).items.query(querySpec, {enableCrossPartitionQuery:true}).toArray();
526442
for (var queryResult of results) {
527443
let resultString = JSON.stringify(queryResult);
528444
console.log(`\tQuery returned ${resultString}\n`);
@@ -569,7 +485,7 @@ Azure Cosmos DB supports replacing the content of items.
569485
console.log(`Replacing item:\n${itemBody.id}\n`);
570486
// Change property 'grade'
571487
itemBody.children[0].grade = 6;
572-
const { item } = await client.database(databaseId).container(containerId).item(itemBody.id).replace(itemBody);
488+
const { item } = await client.database(databaseId).container(containerId).item(itemBody.id, itemBody.Country).replace(itemBody);
573489
};
574490
```
575491

@@ -611,7 +527,7 @@ Azure Cosmos DB supports deleting JSON items.
611527
* Delete the item by ID.
612528
*/
613529
async function deleteFamilyItem(itemBody) {
614-
await client.database(databaseId).container(containerId).item(itemBody.id).delete(itemBody);
530+
await client.database(databaseId).container(containerId).item(itemBody.id, itemBody.Country).delete(itemBody);
615531
console.log(`Deleted item:\n${itemBody.id}\n`);
616532
};
617533
```
@@ -686,148 +602,7 @@ Deleting the created database will remove the database and all children resource
686602

687603
Altogether, your code should look like this:
688604

689-
```javascript
690-
const CosmosClient = require('@azure/cosmos').CosmosClient;
691-
692-
const config = require('./config');
693-
694-
const endpoint = config.endpoint;
695-
const masterKey = config.primaryKey;
696-
697-
const HttpStatusCodes = { NOTFOUND: 404 };
698-
699-
const databaseId = config.database.id;
700-
const containerId = config.container.id;
701-
702-
const client = new CosmosClient({ endpoint: endpoint, auth: { masterKey: masterKey } });
703-
704-
/**
705-
* Create the database if it does not exist
706-
*/
707-
async function createDatabase() {
708-
const { database } = await client.databases.createIfNotExists({ id: databaseId });
709-
console.log(`Created database:\n${database.id}\n`);
710-
}
711-
712-
/**
713-
* Read the database definition
714-
*/
715-
async function readDatabase() {
716-
const { body: databaseDefinition } = await client.database(databaseId).read();
717-
console.log(`Reading database:\n${databaseDefinition.id}\n`);
718-
}
719-
720-
/**
721-
* Create the container if it does not exist
722-
*/
723-
async function createContainer() {
724-
const { container } = await client.database(databaseId).containers.createIfNotExists({ id: containerId });
725-
console.log(`Created container:\n${config.container.id}\n`);
726-
}
727-
728-
/**
729-
* Read the container definition
730-
*/
731-
async function readContainer() {
732-
const { body: containerDefinition } = await client.database(databaseId).container(containerId).read();
733-
console.log(`Reading container:\n${containerDefinition.id}\n`);
734-
}
735-
736-
/**
737-
* Create family item if it does not exist
738-
*/
739-
async function createFamilyItem(itemBody) {
740-
try {
741-
// read the item to see if it exists
742-
const { item } = await client.database(databaseId).container(containerId).item(itemBody.id).read();
743-
console.log(`Item with family id ${itemBody.id} already exists\n`);
744-
}
745-
catch (error) {
746-
// create the family item if it does not exist
747-
if (error.code === HttpStatusCodes.NOTFOUND) {
748-
const { item } = await client.database(databaseId).container(containerId).items.create(itemBody);
749-
console.log(`Created family item with id:\n${itemBody.id}\n`);
750-
} else {
751-
throw error;
752-
}
753-
}
754-
};
755-
756-
/**
757-
* Query the container using SQL
758-
*/
759-
async function queryContainer() {
760-
console.log(`Querying container:\n${config.container.id}`);
761-
762-
// query to return all children in a family
763-
const querySpec = {
764-
query: "SELECT VALUE r.children FROM root r WHERE r.lastName = @lastName",
765-
parameters: [
766-
{
767-
name: "@lastName",
768-
value: "Andersen"
769-
}
770-
]
771-
};
772-
773-
const { result: results } = await client.database(databaseId).container(containerId).items.query(querySpec).toArray();
774-
for (var queryResult of results) {
775-
let resultString = JSON.stringify(queryResult);
776-
console.log(`\tQuery returned ${resultString}\n`);
777-
}
778-
};
779-
780-
/**
781-
* Replace the item by ID.
782-
*/
783-
async function replaceFamilyItem(itemBody) {
784-
console.log(`Replacing item:\n${itemBody.id}\n`);
785-
// Change property 'grade'
786-
itemBody.children[0].grade = 6;
787-
const { item } = await client.database(databaseId).container(containerId).item(itemBody.id).replace(itemBody);
788-
};
789-
790-
/**
791-
* Delete the item by ID.
792-
*/
793-
async function deleteFamilyItem(itemBody) {
794-
await client.database(databaseId).container(containerId).item(itemBody.id).delete(itemBody);
795-
console.log(`Deleted item:\n${itemBody.id}\n`);
796-
};
797-
798-
/**
799-
* Cleanup the database and container on completion
800-
*/
801-
async function cleanup() {
802-
await client.database(databaseId).delete();
803-
}
804-
805-
/**
806-
* Exit the app with a prompt
807-
* @param {message} message - The message to display
808-
*/
809-
function exit(message) {
810-
console.log(message);
811-
console.log('Press any key to exit');
812-
process.stdin.setRawMode(true);
813-
process.stdin.resume();
814-
process.stdin.on('data', process.exit.bind(process, 0));
815-
}
816-
817-
createDatabase()
818-
.then(() => readDatabase())
819-
.then(() => createContainer())
820-
.then(() => readContainer())
821-
.then(() => createFamilyItem(config.items.Andersen))
822-
.then(() => createFamilyItem(config.items.Wakefield))
823-
.then(() => queryContainer())
824-
.then(() => replaceFamilyItem(config.items.Andersen))
825-
.then(() => queryContainer())
826-
.then(() => deleteFamilyItem(config.items.Andersen))
827-
.then(() => cleanup())
828-
.then(() => { exit(`Completed successfully`); })
829-
.catch((error) => { exit(`Completed with error ${JSON.stringify(error)}`) });
830-
```
605+
[!code-javascript[nodejs-get-started](~/cosmosdb-nodejs-get-started/app.js)]
831606

832607
In your terminal, locate your ```app.js``` file and run the command:
833608

0 commit comments

Comments
 (0)