"Invalid partition key" 使用 Node.js 进行 REST 调用以从 Azure Cosmos DB 检索单个文档时
"Invalid partition key" when making a REST call using Node.js to retrieve a single document from Azure Cosmos DB
背景
我正在尝试开发一个演示,使用 REST 调用从 Cosmos DB SQL API 中提取单个文档。我在 Azure 中有一个数据库,这个数据库有一个集合。该集合目前包含两个对象。该集合是使用分区键“/name”创建的。例如,如果我想检索一个集合本身,下面的代码就可以工作。但是,我需要使用特定集合中的文档 ID 来获取文档。正如我提到的,当涉及到一个集合时,我得到了 200 个响应,但是单个文档请求吐出 "Partition Key 'name' or '/name' (or whatever as this point) is invalid."
我试过的
我试过各种方法来正确配置头文件。目前,数据库中的两个对象如下所示:
{
"id": "test2",
"name": "bla2",
"_rid": "knQwAMkBmw4CAAAAAAAAAA==",
"_self": "dbs/knQwAA==/colls/knQwAMkBmw4=/docs/knQwAMkBmw4CAAAAAAAAAA==/",
"_etag": "\"140085d3-0000-0d00-0000-5cd760670000\"",
"_attachments": "attachments/",
"_ts": 1557618791
}
{
"id": "test",
"name": "bla1",
"_rid": "knQwAMkBmw4BAAAAAAAAAA==",
"_self": "dbs/knQwAA==/colls/knQwAMkBmw4=/docs/knQwAMkBmw4BAAAAAAAAAA==/",
"_etag": "\"140079d3-0000-0d00-0000-5cd75e680000\"",
"_attachments": "attachments/",
"_ts": 1557618280
}
这些几乎是我想要的输出。老实说,我已经无计可施了。我已经在谷歌上搜索了几个小时,但我就是做对了。调用已授权。关于如何正确配置分区键,有人能指出正确的方向吗?
代码
var request = require("request");
var crypto = require("crypto");
function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceLink, date, masterKey) {
var key = new Buffer(masterKey, "base64");
var text = (verb || "").toLowerCase() + "\n" +
(resourceType || "").toLowerCase() + "\n" +
(resourceLink || "") + "\n" +
date.toLowerCase() + "\n" +
"" + "\n";
var body = new Buffer(text, "utf8");
var signature = crypto.createHmac("sha256", key).update(body).digest("base64");
var MasterToken = "master";
var TokenVersion = "1.0";
return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);
}
var mkey = '{my-master-key}';
var resourceType = 'docs';
var resourceLink = 'dbs/{MyDatabaseId}/colls/{MyCollId}/docs/test2';
var verb = 'GET';
var date = new Date().toUTCString()
var options = { method: 'GET',
url: 'https://{mycosmosdb}.documents.azure.com/dbs/{MyDatabaseId}/colls/{MyCollId}/docs/test2',
headers:
{ 'cache-control': 'no-cache',
Connection: 'keep-alive',
'accept-encoding': 'gzip, deflate',
'x-ms-documentdb-query-enablecrosspartition': true,
'Cache-Control': 'no-cache',
'x-ms-documentdb-PartitionKey': [ "name" ],
'x-ms-date': date,
'x-ms-documentdb-isquery': true,
'User-Agent': 'Microsoft.Azure.Documents.Client/1.6.0.0',
Host: '{mycosmosdb}.documents.azure.com:443',
'Content-Type': 'application/query+json',
Authorization: getAuthorizationTokenUsingMasterKey(verb,resourceType,resourceLink,date,mkey),
'x-ms-version': '2017-02-22',
Accept: 'application/json',
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
错误输出:
{"code":"BadRequest","message":"Partition key name is invalid.\r\nActivityId: f73587d0-20d0-482f-9422-36c214e266d4, \r\nRequestStartTime: 2019-05-11T23:53:34.4517344Z, RequestEndTime: 2019-05-11T23:53:34.4517344Z, Number of regions attempted: 1\r\n, Microsoft.Azure.Documents.Common/2.2.0.0"}
您收到此错误的原因是 x-ms-documentdb-PartitionKey
header 的值应该是文档中 PartitionKey
属性的值,而不是 PartitionKey
.
来自 REST API
文档:
要解决此问题,请更改以下代码行:
'x-ms-documentdb-PartitionKey': [ "name" ]
至
'x-ms-documentdb-PartitionKey': [ "bla2" ]
你不应该得到这个错误。
更新
所以我查看了 Node SDK 中的代码以及它如何传递 PartitionKey header。本质上,header 值需要是一个字符串。
请尝试使用以下值:
'x-ms-documentdb-Partitionkey': "[\"bla2\"]",
我刚刚试过了,对我来说效果很好。
这是我在请求中传递的 headers:
{
'x-ms-documentdb-Partitionkey': "[\"bla2\"]",
'x-ms-date': date,
'authorization': getAuthorizationTokenUsingMasterKey(verb,resourceType,resourceLink,date,mkey),
'x-ms-version': '2017-02-22'
}
背景
我正在尝试开发一个演示,使用 REST 调用从 Cosmos DB SQL API 中提取单个文档。我在 Azure 中有一个数据库,这个数据库有一个集合。该集合目前包含两个对象。该集合是使用分区键“/name”创建的。例如,如果我想检索一个集合本身,下面的代码就可以工作。但是,我需要使用特定集合中的文档 ID 来获取文档。正如我提到的,当涉及到一个集合时,我得到了 200 个响应,但是单个文档请求吐出 "Partition Key 'name' or '/name' (or whatever as this point) is invalid."
我试过的
我试过各种方法来正确配置头文件。目前,数据库中的两个对象如下所示:
{
"id": "test2",
"name": "bla2",
"_rid": "knQwAMkBmw4CAAAAAAAAAA==",
"_self": "dbs/knQwAA==/colls/knQwAMkBmw4=/docs/knQwAMkBmw4CAAAAAAAAAA==/",
"_etag": "\"140085d3-0000-0d00-0000-5cd760670000\"",
"_attachments": "attachments/",
"_ts": 1557618791
}
{
"id": "test",
"name": "bla1",
"_rid": "knQwAMkBmw4BAAAAAAAAAA==",
"_self": "dbs/knQwAA==/colls/knQwAMkBmw4=/docs/knQwAMkBmw4BAAAAAAAAAA==/",
"_etag": "\"140079d3-0000-0d00-0000-5cd75e680000\"",
"_attachments": "attachments/",
"_ts": 1557618280
}
这些几乎是我想要的输出。老实说,我已经无计可施了。我已经在谷歌上搜索了几个小时,但我就是做对了。调用已授权。关于如何正确配置分区键,有人能指出正确的方向吗?
代码
var request = require("request");
var crypto = require("crypto");
function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceLink, date, masterKey) {
var key = new Buffer(masterKey, "base64");
var text = (verb || "").toLowerCase() + "\n" +
(resourceType || "").toLowerCase() + "\n" +
(resourceLink || "") + "\n" +
date.toLowerCase() + "\n" +
"" + "\n";
var body = new Buffer(text, "utf8");
var signature = crypto.createHmac("sha256", key).update(body).digest("base64");
var MasterToken = "master";
var TokenVersion = "1.0";
return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);
}
var mkey = '{my-master-key}';
var resourceType = 'docs';
var resourceLink = 'dbs/{MyDatabaseId}/colls/{MyCollId}/docs/test2';
var verb = 'GET';
var date = new Date().toUTCString()
var options = { method: 'GET',
url: 'https://{mycosmosdb}.documents.azure.com/dbs/{MyDatabaseId}/colls/{MyCollId}/docs/test2',
headers:
{ 'cache-control': 'no-cache',
Connection: 'keep-alive',
'accept-encoding': 'gzip, deflate',
'x-ms-documentdb-query-enablecrosspartition': true,
'Cache-Control': 'no-cache',
'x-ms-documentdb-PartitionKey': [ "name" ],
'x-ms-date': date,
'x-ms-documentdb-isquery': true,
'User-Agent': 'Microsoft.Azure.Documents.Client/1.6.0.0',
Host: '{mycosmosdb}.documents.azure.com:443',
'Content-Type': 'application/query+json',
Authorization: getAuthorizationTokenUsingMasterKey(verb,resourceType,resourceLink,date,mkey),
'x-ms-version': '2017-02-22',
Accept: 'application/json',
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
错误输出:
{"code":"BadRequest","message":"Partition key name is invalid.\r\nActivityId: f73587d0-20d0-482f-9422-36c214e266d4, \r\nRequestStartTime: 2019-05-11T23:53:34.4517344Z, RequestEndTime: 2019-05-11T23:53:34.4517344Z, Number of regions attempted: 1\r\n, Microsoft.Azure.Documents.Common/2.2.0.0"}
您收到此错误的原因是 x-ms-documentdb-PartitionKey
header 的值应该是文档中 PartitionKey
属性的值,而不是 PartitionKey
.
来自 REST API
文档:
要解决此问题,请更改以下代码行:
'x-ms-documentdb-PartitionKey': [ "name" ]
至
'x-ms-documentdb-PartitionKey': [ "bla2" ]
你不应该得到这个错误。
更新
所以我查看了 Node SDK 中的代码以及它如何传递 PartitionKey header。本质上,header 值需要是一个字符串。
请尝试使用以下值:
'x-ms-documentdb-Partitionkey': "[\"bla2\"]",
我刚刚试过了,对我来说效果很好。
这是我在请求中传递的 headers:
{
'x-ms-documentdb-Partitionkey': "[\"bla2\"]",
'x-ms-date': date,
'authorization': getAuthorizationTokenUsingMasterKey(verb,resourceType,resourceLink,date,mkey),
'x-ms-version': '2017-02-22'
}