在存储过程中获取多个文档 (Azure DocumentDB)
Fetch multiple documents in a stored procedure (Azure DocumentDB)
我有两种文档类型,Listing 和 Products。 Listing 对象包含特定国家/地区的产品列表,如下所示:
列表:
{
"Name": "Default",
"Countries": {
"_default": [
"4QlxAPFcCAAPAAAAAAAAAA==",
"4QlxAPFcCAAHAAAAAAAAAA=="
],
"US": [
"4QlxAPFcCAAIAAAAAAAAAA==",
"4QlxAPFcCAAHAAAAAAAAAA=="
]
},
"Type": "Listing",
"id": "dfed1839-07c5-482b-81c5-669b1dbcd0b6",
"_rid": "4QlxAPFcCAAEAAAAAAAAAA=="
}
产品:
{
"Name": "Widget",
"Price": 3.45,
"Type": "Product",
"_rid": "4QlxAPFcCAAHAAAAAAAAAA=="
}
我的目标是在 Azure DocumentDB 集合中创建一个 存储过程,它带有两个参数,rid
和 country
,这实际上会获取清单文件,以及该国的文件,以尽可能最有效的方式。我的假设是,使用 getContext().getCollection().readDocument(...)
通过其资源 ID 加载文档是最快的方法,因此尝试为此创建一个存储过程。
我的尝试是嵌套连续调用(回调地狱?),使用 generator/iterators 和 yield,然后使用纯 Promise
方法。所有的尝试都给出了相同的结果:
它将获取第一个文档,但在接收到文档后会突然结束。
作为参考,这是我最近的尝试:
function test(rid, country) {
var collection = getContext().getCollection();
var collectionSelfLink = collection.getSelfLink();
var docsLink = collectionSelfLink + "docs/";
var body = getContext().getResponse().setBody;
function getDocument(rid) {
return new Promise(function(resolve, reject) {
var accepted = collection.readDocument(docsLink + rid, (err, doc, opts) => {
resolve(doc);
});
if (!accepted)
reject("Not accepted");
});
}
getDocument(rid)
.then(doc => {
body("0. First step"); // set test body
// Countries is a Dictionary<string, string[]> with resource ids
return doc.Countries[country] || doc.Countries["_default"];
})
// This is how far it gets, resulting in response "1. Documents to fetch: 2"
.then(a => body("1. Documents to fetch: " + a.length))
.then(a => a.map(function(productId) { return getDoument(productId); }))
.then(a => body("2. It should come this far, right?"))
.then(a => Promise.all(a))
.then(a => body(a))
.catch(function(e) { throw new Error(JSON.stringify(e)); });
}
事实证明,嵌套调用 do 实际上可行,如果您经常更改响应正文(?)
以下过程按预期工作:
function test(rid, country) {
var collection = getContext().getCollection();
var collectionSelfLink = collection.getSelfLink();
var docsLink = collectionSelfLink + "docs/";
var body = getContext().getResponse().setBody;
var accepted = collection.readDocument(docsLink + rid, (err, doc, opts) => {
if (err) throw new Error(err.message);
// Countries is a Dictionary<string, string[]> with resource ids
var offerIds = doc.Countries[country] || doc.Countries["_default"];
var result = [];
for (var docId of offerIds) {
var subAccepted =
collection.readDocument(docsLink + docId, (err, doc, opts) => {
if (err) throw new Error(err.message);
result.push(doc);
});
if (!subAccepted)
throw new Error("A subsequent request was not accepted");
body(result); // <-- Note, setting body in each iteration.
}
});
if (!accepted)
throw new Error("The request was not accepted");
}
我有两种文档类型,Listing 和 Products。 Listing 对象包含特定国家/地区的产品列表,如下所示:
列表:
{
"Name": "Default",
"Countries": {
"_default": [
"4QlxAPFcCAAPAAAAAAAAAA==",
"4QlxAPFcCAAHAAAAAAAAAA=="
],
"US": [
"4QlxAPFcCAAIAAAAAAAAAA==",
"4QlxAPFcCAAHAAAAAAAAAA=="
]
},
"Type": "Listing",
"id": "dfed1839-07c5-482b-81c5-669b1dbcd0b6",
"_rid": "4QlxAPFcCAAEAAAAAAAAAA=="
}
产品:
{
"Name": "Widget",
"Price": 3.45,
"Type": "Product",
"_rid": "4QlxAPFcCAAHAAAAAAAAAA=="
}
我的目标是在 Azure DocumentDB 集合中创建一个 存储过程,它带有两个参数,rid
和 country
,这实际上会获取清单文件,以及该国的文件,以尽可能最有效的方式。我的假设是,使用 getContext().getCollection().readDocument(...)
通过其资源 ID 加载文档是最快的方法,因此尝试为此创建一个存储过程。
我的尝试是嵌套连续调用(回调地狱?),使用 generator/iterators 和 yield,然后使用纯 Promise
方法。所有的尝试都给出了相同的结果:
它将获取第一个文档,但在接收到文档后会突然结束。
作为参考,这是我最近的尝试:
function test(rid, country) {
var collection = getContext().getCollection();
var collectionSelfLink = collection.getSelfLink();
var docsLink = collectionSelfLink + "docs/";
var body = getContext().getResponse().setBody;
function getDocument(rid) {
return new Promise(function(resolve, reject) {
var accepted = collection.readDocument(docsLink + rid, (err, doc, opts) => {
resolve(doc);
});
if (!accepted)
reject("Not accepted");
});
}
getDocument(rid)
.then(doc => {
body("0. First step"); // set test body
// Countries is a Dictionary<string, string[]> with resource ids
return doc.Countries[country] || doc.Countries["_default"];
})
// This is how far it gets, resulting in response "1. Documents to fetch: 2"
.then(a => body("1. Documents to fetch: " + a.length))
.then(a => a.map(function(productId) { return getDoument(productId); }))
.then(a => body("2. It should come this far, right?"))
.then(a => Promise.all(a))
.then(a => body(a))
.catch(function(e) { throw new Error(JSON.stringify(e)); });
}
事实证明,嵌套调用 do 实际上可行,如果您经常更改响应正文(?)
以下过程按预期工作:
function test(rid, country) {
var collection = getContext().getCollection();
var collectionSelfLink = collection.getSelfLink();
var docsLink = collectionSelfLink + "docs/";
var body = getContext().getResponse().setBody;
var accepted = collection.readDocument(docsLink + rid, (err, doc, opts) => {
if (err) throw new Error(err.message);
// Countries is a Dictionary<string, string[]> with resource ids
var offerIds = doc.Countries[country] || doc.Countries["_default"];
var result = [];
for (var docId of offerIds) {
var subAccepted =
collection.readDocument(docsLink + docId, (err, doc, opts) => {
if (err) throw new Error(err.message);
result.push(doc);
});
if (!subAccepted)
throw new Error("A subsequent request was not accepted");
body(result); // <-- Note, setting body in each iteration.
}
});
if (!accepted)
throw new Error("The request was not accepted");
}