在过去的几年里,我学到了很多东西,我想分享我学到的东西,但是有一件事让我无法参与。我希望我能打破这种沉默,定期发表文章。
继续我的工作Cerebrata Cerulean,我有机会与Node.js和一些令人惊叹的Azure服务一起工作。在这一系列帖子中,我将重点关注使用Azure Cosmos DB用他们的节点软件开发工具包服务。我们将涵盖与各种实体的合作,如数据库、容器(集合)、文档等。使用节点软件开发工具包。
在这篇文章中,我们将重点关注数据库。我们将看到如何在数据库上执行各种操作,如列表、创建、删除等。
在我们开始之前,您需要做一些事情:
假设您已经创建了一个文件夹并安装了软件包,让我们创建一个名为“database-samples.js”的文件,并在其中添加以下代码行:
const {Promise} = require('bluebird');
const {CosmosClient, Database} = require('@azure/cosmos');
const accountEndpoint = 'https://account-name.documents.azure.com:443/';
const accountKey = 'yM0g3KnPANPpBgKLi34OMz1UZ7Png2pjQrs209IrrQkyhtqZKmALludel1nizEOqeJMm1gavLb0dS0gAoMw3Pw==';
/**
** Method to get client connection object.
**/
const getClient = () => {
return new CosmosClient({
endpoint: accountEndpoint,
auth: {
masterKey: accountKey
}
});
};
请确保使用您的宇宙数据库帐户凭证的值。
我们现在都准备好前进了!
还有一件事。因为我们将包含异步/等待和承诺的代码,所以我们将在方法名称前面加上我们正在使用的方法。例如,“列表数据库同步”和“列表数据库同步”分别表示异步/等待和承诺。
假设我们想要列出一个帐户中的所有数据库。我们将这样做。
下面是使用异步/等待列出数据库的代码:
const listDatabasesAsync = async () => {
const client = getClient();
const iterator = await client.databases.readAll().toArray();
const databases = [];
iterator.result.forEach((item) => {
databases.push(item);
});
return databases;
};
我们在这里做的第一件事是获取CosmosClient
然后使用类中的方法读取所有数据库。这个方法的输出将是一个数组,看起来如下所示:
[
{
id: 'database-000',//name of the database
_rid: 'xD4MAA==',//system assigned id to the database
_self: 'dbs/xD4MAA==/',//self link
_etag: '"00004d00-0000-0100-0000-5cf55d1d0000"',//etag
_colls: 'colls/',
_users: 'users/',
_ts: 1559584029 //timestamp (in unix epoch)
},
{ id: 'database-001',
_rid: 'B+kiAA==',
_self: 'dbs/B+kiAA==/',
_etag: '"00004e00-0000-0100-0000-5cf55d230000"',
_colls: 'colls/',
_users: 'users/',
_ts: 1559584035
}
]
下面是使用promise列出数据库的代码:
const listDatabasesPromise = () => {
return new Promise((resolve, reject) => {
const client = getClient();
client.databases.readAll().toArray()
.then((databasesListingResult) => {
const databases = [];
databasesListingResult.result.forEach((item) => {
databases.push(item);
});
resolve(databases);
})
.catch((error) => {
reject(error);
});
});
}
接下来,让我们看看如何在宇宙数据库帐户中创建一个数据库。假设我们想创建一个名为“awesomedb”的数据库。
下面是使用异步/等待创建数据库的代码:
const createDatabaseAsync = async (databaseId) => {
const databaseDefinition = {
id: databaseId
};
const client = getClient();
const result = await client.databases.create(databaseDefinition);
return result;
};
//This is how you would call it.
const runAsync = async () => {
let databaseName = 'awesomedb';
console.log(`creating database: ${databaseName}`);
const result = await createDatabaseAsync(databaseName);
console.log(result);
};
runAsync().catch((error) => {
console.log(error);
});
我们在这里做的是首先得到一个CosmosClient
然后在类中调用方法。
此方法的输出是一个具有以下关键成员的对象:
请注意,如果帐户中已经存在同名的数据库,上述方法将会失败。
要解决这个问题,我们只需使用createIfNotExists
方法。就这么简单!下面是这样做的代码:
const createDatabaseIfNotExistsAsync = async (databaseId) => {
const databaseDefinition = {
id: databaseId
};
const client = getClient();
const result = await client.databases.createIfNotExists(databaseDefinition);
return result;
};
如果你要使用承诺,下面是代码:
const createDatabasePromise = (databaseId) => {
return new Promise((resolve, reject) => {
const databaseDefinition = {
id: databaseId
};
const client = getClient();
client.databases.create(databaseDefinition)
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
});
});
};
const createDatabaseIfNotExistsPromise = (databaseId) => {
return new Promise((resolve, reject) => {
const databaseDefinition = {
id: databaseId
};
const client = getClient();
client.databases.createIfNotExists(databaseDefinition)
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
});
});
};
默认情况下,当您创建一个数据库时,它没有自己的吞吐量。该数据库中的每个容器都有自己的吞吐量,这是您在创建该容器时定义的。
但是,您想要做的是在数据库级别定义吞吐量,以便所有容器共享该吞吐量。如果你来自于SQL数据库世界,这有点类似于弹性数据库池(尽管相似性仅在概念层面;这里有一些显著的不同,但这超出了本文的范围。
因此,假设我们想要创建一个名为“awesomedb”的数据库,提供1000 RU/s的吞吐量。
下面是使用异步/等待创建具有预配吞吐量的数据库的代码:
const createDatabaseWithProvisionedThroughputAsync = async (databaseId, throughput) => {
const databaseDefinition = {
id: databaseId
};
const requestOptions = {
offerThroughput: throughput
};
const client = getClient();
const result = await client.databases.create(databaseDefinition, requestOptions);
return result;
};
//This is how you would call it.
const runAsync = async () => {
let databaseName = 'awesomedb';
console.log(`creating database: ${databaseName}`);
const result = await createDatabaseWithProvisionedThroughputAsync(databaseName, 1000);
console.log(result);
};
runAsync().catch((error) => {
console.log(error);
});
const createDatabaseIfNotExistsWithProvisionedThroughputAsync = async (databaseId, throughput) => {
const databaseDefinition = {
id: databaseId
};
const requestOptions = {
offerThroughput: throughput
};
const client = getClient();
const result = await client.databases.createIfNotExists(databaseDefinition, requestOptions);
return result;
};
//This is how you would call it.
const runAsync = async () => {
let databaseName = 'awesomedb';
console.log(`creating database: ${databaseName}`);
const result = await createDatabaseWithProvisionedThroughputAsync(databaseName, 1000);
console.log(result);
};
runAsync().catch((error) => {
console.log(error);
});
如果您查看上面的代码,您会注意到它非常类似于我们用来创建没有提供吞吐量的数据库的代码。要创建具有预配吞吐量的数据库,我们只需定义一个requestOption
对象,并将我们想要的吞吐量指定为offerThroughput
财产。真的就这么简单!
请注意,在写这篇文章的时候,一个数据库可以拥有的最小吞吐量是400 RU/s,您可以通过编程设置的最大吞吐量是100000 RU/s。对于超过这个限制的吞吐量,您需要调用Azure支持。
如果你要使用承诺,下面是代码:
const createDatabaseWithProvisionedThroughputPromise = (databaseId, throughput) => {
return new Promise((resolve, reject) => {
const databaseDefinition = {
id: databaseId
};
const requestOptions = {
offerThroughput: throughput
};
const client = getClient();
client.databases.create(databaseDefinition, requestOptions)
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
})
});
};
const createDatabaseIfNotExistsWithProvisionedThroughputPromise = (databaseId, throughput) => {
return new Promise((resolve, reject) => {
const databaseDefinition = {
id: databaseId
};
const requestOptions = {
offerThroughput: throughput
};
const client = getClient();
client.databases.createIfNotExists(databaseDefinition, requestOptions)
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
});
});
};
接下来,让我们看看如何读取数据库的属性。
下面是使用异步/等待获得具有预配吞吐量的数据库属性的代码:
const getDatabasePropertiesAsync = async (databaseId) => {
const client = getClient();
const db = client.database(databaseId);
const result = await db.read();
return result;
}
代码非常简单。首先,我们得到一个CosmosClient
然后获取类的一个实例,然后我们调用该对象上的方法。
此方法的输出是一个具有以下关键成员的对象:
如果你要使用承诺,下面是代码:
const getDatabasePropertiesPromise = (databaseId) => {
return new Promise((resolve, reject) => {
const client = getClient();
const db = client.database(databaseId);
db.read()
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
});
});
};
接下来,让我们看看如何删除数据库。
下面是使用异步/等待删除数据库的代码:
const deleteDatabaseAsync = async (databaseId) => {
const client = getClient();
const db = client.database(databaseId);
await db.delete();
return true;
};
同样,代码非常简单。首先,我们得到一个CosmosClient
然后得到一个类的实例,然后我们调用这个对象上的方法。
我唯一的愿望是软件开发工具包引入一个功能,比如deleteIfExists
,类似于createIfNotExists
。
如果你要使用承诺,下面是代码:
const deleteDatabasePromise = (databaseId) => {
return new Promise((resolve, reject) => {
const client = getClient();
const db = client.database(databaseId);
db.delete()
.then((result) => {
resolve(true);
})
.catch((error) => {
reject(error);
});
});
};
假设我们创建了一个具有调配吞吐量的数据库,我们想知道该吞吐量是多少。
考虑到我们定义了数据库的吞吐量,我们希望数据库的一个属性能告诉我们这一点,但事实并非如此:)。
要获得数据库(或容器)的吞吐量,实际上需要使用应用编程接口。让我们看看这是如何工作的。
下面是使用异步/等待获得数据库报价的代码:
const getDatabaseOfferAsync = async (databaseId) => {
const client = getClient();
const db = client.database(databaseId);
const {body: databaseProperties} = await db.read();
const selfLink = databaseProperties._self;
const querySpec = {
query: 'SELECT * FROM root r WHERE r.resource = @link',
parameters: [{
name: '@link',
value: selfLink
}]
};
const offerListingResult = await client.offers.query(querySpec).toArray();
const offer = offerListingResult.result[0];
return offer;
};
为了获得资源的报价(在本例中是数据库),我们需要selfLink
资源属性。这就是我们在上面的代码中所做的。
首先,我们得到一个CosmosClient
。接下来,我们创建一个实例Database
并读取数据库属性,这样我们就可以访问_self
数据库属性。然后,我们调用类中的方法来获取数据库中可用的报价。
输出如下所示:
{
resource: 'dbs/dEwOAA==/',
offerType: 'Invalid',
offerResourceId: 'dEwOAA==',
offerVersion: 'V2',
content:
{
offerThroughput: 400,
offerIsRUPerMinuteThroughputEnabled: false
},
id: 'BlZx',
_rid: 'BlZx',
_self: 'offers/BlZx/',
_etag: '"00005200-0000-0100-0000-5cf5ee200000"',
_ts: 1559621152
}
要获得吞吐量,只需阅读offerThroughtput
的属性content
结果的属性。
如果你要使用承诺,下面是代码:
const getDatabaseOfferPromise = (databaseId) => {
return new Promise((resolve, reject) => {
const client = getClient();
const db = client.database(databaseId);
db.read()
.then((result) => {
const databaseProperties = result.body;
const selfLink = databaseProperties._self;
const querySpec = {
query: 'SELECT * FROM root r WHERE r.resource = @link',
parameters: [{
name: '@link',
value: selfLink
}]
};
client.offers.query(querySpec).toArray()
.then((offerListingResult) => {
const offer = offerListingResult.result[0];
resolve(offer);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error);
});
});
};
这是我们为这篇文章做的最后一件事。假设您创建了一个具有一些预配吞吐量的数据库,现在您想要更改该吞吐量。
实现这一点的方法是获取数据库的报价,更新offerThroughtput
属性,然后用修改后的要约替换现有要约。
下面是使用异步/等待更新数据库报价的代码:
const updateDatabaseProvisionedThroughputAsync = async (databaseId, provisionedThroughput) => {
const offerDetails = await getDatabaseOfferAsync(databaseId);
offerDetails.content.offerThroughput = provisionedThroughput;
const client = getClient();
const offer = client.offer(offerDetails.id);
await offer.replace(offerDetails);
};
代码非常简单。首先,我们通过我们的getDatabaseOfferAsync
方法。然后,我们将更新该产品中提供的吞吐量。
接下来,我们得到一个CosmosClient
。使用它和报价id,我们创建一个类的实例,最后调用该类上的方法来替换报价。
如果你要使用承诺,下面是代码:
const updateDatabaseProvisionedThroughputPromise = (databaseId, provisionedThroughput) => {
return new Promise((resolve, reject) => {
getDatabaseOfferPromise(databaseId)
.then((offerDetails) => {
offerDetails.content.offerThroughput = provisionedThroughput;
const client = getClient();
const offer = client.offer(offerDetails.id);
offer.replace(offerDetails)
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error);
});
});
};
这篇文章到此为止!在下一系列文章中,我们将对容器(集合)、文档和其他东西做同样的事情,所以请继续关注。
如果您在这篇文章中发现代码样本或任何其他信息有任何问题,请让我知道,我会尽快解决它们。
快乐编码!