Is there a way to recursively call stored procedures (or even UDFs if that will work) against DocumentDB documents?
We have a document that looks something like this:
{
"docID" : "my_id",
"owner" : "fred",
"items" : [
{
"itemID" : "1",
"type" : "item",
"value" : 3
},
{
"itemID" : "2",
"type" : "group",
"items" : [
{
"itemID" : "2.1",
"type" : "group",
"items" : [
{
"itemID" : "2.1.1",
"type" : "item",
"value" : 2
},
{
"itemID" : "2.1.2",
"type" : "item",
"value" : 4
}
]
},
{
"itemID" : "2.2",
"type" : "item",
"value" : 1
}
]
}
]
}
Any time we have "items"
, that "items"
array can contain entries that are a mix of "type" : "item"
and "type" : "group"
. Entries that are of "type" : "item"
have a simple "value"
field that needs to be summed. Entries that are of "type" : "group"
have an "items"
array... and so on. In theory, there is no limit to the level of recursion, which I acknowledge is a problem, but in practice, the levels will rarely get below 4 or 5 deep.
Pseudocode for what I'm trying to write looks something like this:
function sumValues(items) {
int total = 0;
forEach(item in items) {
if (item.type == "item") {
total += item.value;
} else {
total += sumValues(item.items);
}
}
return total;
}
function sumAllValues() {
var ctx = getContext();
var coll = ctx.getCollection();
var response = ctx.getResponse();
// query for docs by owner
var filterQuery = 'SELECT * FROM Docs d where d.owner = \\\"fred\\\"';
var done = coll.queryDocuments(coll.getSelfLink(), filterQuery, {},
function (err, docs, options) {
if (err) throw new Error ('Error' + err.message);
var total = 0;
docs.forEach(function(doc) {
total += sumTotals(doc.items);
});
response.setBody('Total: ' + total);
});
}
Is this even possible? Does DocumentDB support calling a sproc from another sproc? Can a sproc call itself?
I have found a few DocumentDB stored procedure references online, including this and this and this and this plus a host of other pages.
If it's possible, I think I might have to somehow query the collection to get the sproc that I want to call, and then somehow reference the sproc, instead of just calling sumTotals()
directly as you would with a standalone language.
We're just starting to look at programming with DocumentDB, so we're not completely sure what we can do with it yet. Thanks for any assistance or advice.
I think you're on the right track here.
It is not possible to execute a stored procedure from within a stored procedure.
However, you can define JS functions inside a stored procedure, which can be can be referenced, called, and re-used from within that stored procedure.
In this case, simply define your sumValues()
function inside the parent sumAllValues()
stored procedure (just like the swapItems()
example you mentioned).
function sumAllValues() {
var ctx = getContext();
var coll = ctx.getCollection();
var response = ctx.getResponse();
// query for docs by owner
var filterQuery = 'SELECT * FROM Docs d where d.owner = \\\"fred\\\"';
var done = coll.queryDocuments(coll.getSelfLink(), filterQuery, {},
function (err, docs, options) {
if (err) throw new Error ('Error' + err.message);
var total = 0;
docs.forEach(function(doc) {
total += sumValues(doc.items);
});
response.setBody('Total: ' + total);
});
function sumValues(items) {
int total = 0;
items.forEach(function(item) {
if (item.type == "item") {
total += item.value;
} else {
total += sumValues(item.items);
}
});
return total;
}
}
You can also define UDFs for logic you'd like to share and re-use across multiple stored procedures and queries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With