gpt4 book ai didi

azure - 如何在 CosmosDB Javascript 存储过程中执行批量字段重命名

转载 作者:行者123 更新时间:2023-12-03 02:57:26 27 4
gpt4 key购买 nike

我一直在关注显示的 javascript 存储过程示例 here

下面的代码尝试编写更新存储过程示例的修改版本。这就是我正在尝试做的事情:

  • 我不想对单个文档进行操作,而是想执行更新所提供的查询返回的文档集。
  • (可选)返回响应正文中更新文档的计数。

代码如下:

function updateSproc(query, update) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var response = getContext().getResponse();
var responseBody = {
updated: 0,
continuation: false
};

// Validate input.
if (!query) throw new Error("The query is undefined or null.");
if (!update) throw new Error("The update is undefined or null.");

tryQueryAndUpdate();

// Recursively queries for a document by id w/ support for continuation tokens.
// Calls tryUpdate(document) as soon as the query returns a document.
function tryQueryAndUpdate(continuation) {
var requestOptions = {continuation: continuation};

var isAccepted = collection.queryDocuments(collectionLink, query, requestOptions, function (err, documents, responseOptions) {
if (err) throw err;

if (documents.length > 0) {
tryUpdate(documents);
}
else if (responseOptions.continuation) {
// Else if the query came back empty, but with a continuation token; repeat the query w/ the token.
tryQueryAndUpdate(responseOptions.continuation);
}
else {
// Else if there are no more documents and no continuation token - we are finished updating documents.
responseBody.continuation = false;
response.setBody(responseBody);
}
});

// If we hit execution bounds - return continuation:true
if (!isAccepted) {
response.setBody(responseBody);
}
}

// Updates the supplied document according to the update object passed in to the sproc.
function tryUpdate(documents) {
if (documents.length > 0) {
var requestOptions = {etag: documents[0]._etag};

// Rename!
rename(documents[0], update);

// Update the document.
var isAccepted = collection.replaceDocument(
documents[0]._self,
documents[0],
requestOptions,
function (err, updatedDocument, responseOptions) {
if (err) throw err;

responseBody.updated++;
documents.shift();
// Try updating the next document in the array.
tryUpdate(documents);
}
);

if (!isAccepted) {
response.setBody(responseBody);
}
}
else {
tryQueryAndUpdate();
}
}

// The $rename operator renames a field.
function rename(document, update) {
var fields, i, existingFieldName, newFieldName;

if (update.$rename) {
fields = Object.keys(update.$rename);
for (i = 0; i < fields.length; i++) {
existingFieldName = fields[i];
newFieldName = update.$rename[fields[i]];

if (existingFieldName == newFieldName) {
throw new Error("Bad $rename parameter: The new field name must differ from the existing field name.")
} else if (document[existingFieldName]) {
// If the field exists, set/overwrite the new field name and unset the existing field name.
document[newFieldName] = document[existingFieldName];
delete document[existingFieldName];
} else {
// Otherwise this is a noop.
}
}
}
}
}
<小时/>

我通过 Azure Web 门户运行此存储过程,这些是我的输入参数:

  • 从根目录中选择 *
  • {$重命名:{A:“B”}}

我的文档看起来像这样:

{ id: someId, A: "ChangeThisField" }

字段重命名后,我希望它们看起来像这样:

{ id: someId, B: "ChangeThisField" }

我正在尝试使用此代码调试两个问题:

  1. 更新后的计数非常不准确。我怀疑我对延续 token 做了一些非常愚蠢的事情 - 部分问题是我不太确定如何处理它。
  2. 重命名本身并未发生。 console.log() 调试显示我永远不会进入重命名函数中的 if (update.$rename) block 。

最佳答案

我修改了您的存储过程代码,如下所示,它对我有用。我没有使用对象或数组作为我的 $rename 参数,我使用了 oldKeynewKey 相反。如果您确实关心参数的构造,则可以将 rename 方法更改回来,这不会影响其他逻辑。请引用我的代码:

function updateSproc(query, oldKey, newKey) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var response = getContext().getResponse();
var responseBody = {
updated: 0,
continuation: ""
};

// Validate input.
if (!query) throw new Error("The query is undefined or null.");
if (!oldKey) throw new Error("The oldKey is undefined or null.");
if (!newKey) throw new Error("The newKey is undefined or null.");

tryQueryAndUpdate();

function tryQueryAndUpdate(continuation) {
var requestOptions = {
continuation: continuation,
pageSize: 1
};

var isAccepted = collection.queryDocuments(collectionLink, query, requestOptions, function (err, documents, responseOptions) {
if (err) throw err;

if (documents.length > 0) {
tryUpdate(documents);
if(responseOptions.continuation){
tryQueryAndUpdate(responseOptions.continuation);
}else{
response.setBody(responseBody);
}

}
});

if (!isAccepted) {
response.setBody(responseBody);
}
}

function tryUpdate(documents) {
if (documents.length > 0) {
var requestOptions = {etag: documents[0]._etag};
// Rename!
rename(documents[0]);

// Update the document.
var isAccepted = collection.replaceDocument(
documents[0]._self,
documents[0],
requestOptions,
function (err, updatedDocument, responseOptions) {
if (err) throw err;

responseBody.updated++;
documents.shift();
// Try updating the next document in the array.
tryUpdate(documents);
}
);

if (!isAccepted) {
response.setBody(responseBody);
}
}
}

// The $rename operator renames a field.
function rename(document) {
if (oldKey&&newKey) {
if (oldKey == newKey) {
throw new Error("Bad $rename parameter: The new field name must differ from the existing field name.")
} else if (document[oldKey]) {
document[newKey] = document[oldKey];
delete document[oldKey];
}
}
}
}

我只有3个测试文档,所以我将pagesize设置为1来测试延续的用法。

测试文档:

enter image description here

输出:

enter image description here

enter image description here

希望对您有帮助。如有任何疑问,请告诉我。

关于azure - 如何在 CosmosDB Javascript 存储过程中执行批量字段重命名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51769124/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com