I need to update some docs(type1) with data from other docs(type2) when they create on CosmosDB. I decided use javascript Azure Functions and cosmosDBTrigger, server-less Azure option. I have problems with binding expressions to configure functions.json for get the doc-type1 associate with doc-type2 that trigger the Function. Any help could be great.
CosmosDB doc-type1:
{
"type": "type1"
"id": "123",
"serial" : "123",
"lastconf": []
}
CosmosDB doc-type2:
{
"type": "type2"
"id": "qwe",
"idtype1" : "123",
"conf1":1
}
function.json
{
"bindings": [{
"name": "documents",
"type": "cosmosDBTrigger",
"direction": "in",
"leaseCollectionName": "leases",
"connectionStringSetting": "_DOCUMENTDB",
"databaseName": "db",
"collectionName": "dbDev",
"createLeaseCollectionIfNotExists": true
},
{
"name": "inputDocumentIn",
"type": "cosmosDB",
"databaseName": "db",
"collectionName": "dbDev",
"id": "{idtype1}", // sqlQuery ??
"connectionStringSetting": "_DOCUMENTDB",
"direction": "in"
},
{
"name": "inputDocumentOut",
"type": "cosmosDB",
"databaseName": "db",
"collectionName": "dbDev",
"createIfNotExists": false,
"connectionStringSetting": "_DOCUMENTDB",
"direction": "out"
} ]
}
index.js:
module.exports = async function(context, documents, inputDocumentIn, inputDocumentOut) {
context.log('JavaScript trigger function processed a request.');
if (!!documents && documents.length > 0) {
context.log('Documents: ', documents);
inputDocumentOut = inputDocumentIn;
inputDocumentOut.lastconf = documents.conf1; //documents[i].conf1; ??
context.log('inputDocumentOut: ', inputDocumentOut);
}
}
The Cosmos DB Trigger sends a list of documents as the payload. Since the content is a list, not a single object/document, using an Input Binding won't work (your inputDocumentIn
binding).
Another thing I noticed by checking your binding configuration, is that your Output binding is writing to the same Container/Account that your Trigger is listening to, you are effectively creating a loop (the document you write will trigger the Function again).
In cases where you want to trigger a Function, receive the changes (documents
), and generate an output, you mostly loop over the results, and output the result into a different container. If you do need to send the output to the same collection, you need to add some logic that filters those from the documents
list.
If you need to execute a query, the execution might also need to happen as part of the loop, there is no binding that can help you there though, you need to have a Client and manually do those operations.
Saving documents in the output binding, that I guess also needs to happen in the loop (as you would want to save multiple per Function execution) can certainly use an array:
module.exports = async function(context, documents, inputDocumentIn, inputDocumentOut) {
context.log('JavaScript trigger function processed a request.');
if (!!documents && documents.length > 0) {
context.log('Documents: ', documents);
var documentsToSave = [];
for(var i = 0; i < documents.length; i++)
{
var document = documents[i];
var documentToSave = {};
// process document, maybe assign property values to documentToSave from document
documentsToSave.push(documentToSave);
}
inputDocumentOut = documentsToSave;
}
}