使用Node.js进行REST调用以从Azure Cosmos DB检索单个文档时,“无效的分区键”

时间:2019-05-12 00:39:00

标签: node.js azure rest azure-cosmosdb-sqlapi

Bakground

我正在尝试开发一个演示,该演示使用REST调用从Cosmos DB SQL API中提取单个文档。我在Azure中有一个数据库,该数据库有一个集合。此集合当前包含两个对象。该集合是使用分区键“ / name”创建的。例如,如果我想检索集合本身,则下面的代码有效。但是,我需要使用特定集合中的文档ID来获取文档。正如我提到的,当涉及到集合时,我收到200的响应,但是一个文档请求吐出“分区键'name'或'/ name'(或此时的任何名称)无效。”

我尝试过的

我尝试了各种方法来正确配置头文件。当前,数据库中的两个对象如下所示:

{
    "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"}

1 个答案:

答案 0 :(得分:0)

出现此错误的原因是因为x-ms-documentdb-PartitionKey标头的值应该是文档中PartitionKey属性的值,而不是PartitionKey的名称。 / p>

摘自REST API文档:

enter image description here

要解决此问题,请更改以下代码行:

'x-ms-documentdb-PartitionKey': [ "name" ]

'x-ms-documentdb-PartitionKey': [ "bla2" ]

而且您不应收到此错误。

更新

因此,我在Node SDK中查找了代码以及它如何传递PartitionKey标头。本质上,标头值必须是字符串。

请尝试使用以下值:

 'x-ms-documentdb-Partitionkey': "[\"bla2\"]",

我刚刚尝试过,对我来说效果很好。

这是我在请求中传递的标头:

  {
    'x-ms-documentdb-Partitionkey': "[\"bla2\"]",
    'x-ms-date': date,
    'authorization': getAuthorizationTokenUsingMasterKey(verb,resourceType,resourceLink,date,mkey),
    'x-ms-version': '2017-02-22'
  }