Programmazione lato server per Azure Cosmos DB: stored procedure, trigger del database e funzioni definite dall'utenteAzure Cosmos DB server-side programming: Stored procedures, database triggers, and UDFs

Suggerimento

L'API SQL (DocumentDB) o API DocumentDB di Azure Cosmos DB è ora denominata API SQL di Azure Cosmos DB.The Azure Cosmos DB DocumentDB API or SQL (DocumentDB) API is now known as Azure Cosmos DB SQL API. Non è necessaria alcuna modifica per continuare a eseguire le app compilate con l'API DocumentDB.You don't need to change anything to continue running your apps built with DocumentDB API. Le funzionalità rimangono invariate.The functionality remains the same.

L'esecuzione integrata e transazionale di JavaScript con il linguaggio di Azure Cosmos DB permette agli sviluppatori di scrivere stored procedure, trigger e funzioni definite dall'utente in modo nativo in ECMAScript 2015 JavaScript.Learn how Azure Cosmos DB’s language integrated, transactional execution of JavaScript lets developers write stored procedures, triggers and user defined functions (UDFs) natively in an ECMAScript 2015 JavaScript. Ciò consente di scrivere la logica dell'applicazione del programma del database che può essere inserita ed eseguita direttamente nelle partizioni di archiviazione del database.This allows you to write database program application logic that can be shipped and executed directly on the database storage partitions.

Per iniziare, è consigliabile guardare il video seguente, in cui Andrew Liu introduce brevemente il modello di programmazione database lato server di Cosmos DB.We recommend getting started by watching the following video, where Andrew Liu provides a brief introduction to Cosmos DB's server-side database programming model.

Tornare quindi a questo articolo, che fornisce risposte alle domande seguenti:Then, return to this article, where you'll learn the answers to the following questions:

  • Come è possibile scrivere una stored procedure, un trigger o una funzione definita dall'utente usando JavaScript?How do I write a a stored procedure, trigger, or UDF using JavaScript?
  • In che modo Cosmos DB garantisce proprietà ACID?How does Cosmos DB guarantee ACID?
  • Come funzionano le transazioni in Cosmos DB?How do transactions work in Cosmos DB?
  • Cosa sono i pre-trigger e i post-trigger e come si scrivono?What are pre-triggers and post-triggers and how do I write one?
  • Come si registra e si esegue una stored procedure, un trigger o una funzione definita dall'utente in modalità RESTful usando HTTP?How do I register and execute a stored procedure, trigger, or UDF in a RESTful manner by using HTTP?
  • Quali SDK di Cosmos DB sono disponibili per la creazione e l'esecuzione di stored procedure, trigger e funzioni definite dall'utente?What Cosmos DB SDKs are available to create and execute stored procedures, triggers, and UDFs?

Introduzione alle stored procedure e alla programmazione delle funzioni definite dall'utenteIntroduction to Stored Procedure and UDF Programming

Questo approccio di "JavaScript come nuovo T-SQL" libera gli sviluppatori di applicazioni dalle complessità delle mancate corrispondenze nel sistema dei tipi e delle tecnologie di mapping relazionale a oggetti.This approach of “JavaScript as a modern day T-SQL” frees application developers from the complexities of type system mismatches and object-relational mapping technologies. Comporta anche una serie di vantaggi intrinseci che possono essere utili per creare applicazioni avanzate:It also has a number of intrinsic advantages that can be utilized to build rich applications:

  • Logica procedurale: come linguaggio di programmazione di alto livello, JavaScript offre un'interfaccia completa e familiare per esprimere la logica di business.Procedural Logic: JavaScript as a high level programming language, provides a rich and familiar interface to express business logic. È possibile eseguire sequenze complesse di operazioni a ridosso dei dati.You can perform complex sequences of operations closer to the data.
  • Transazioni atomiche: Cosmos DB garantisce che le operazioni di database all'interno di una singola stored procedure o un trigger siano atomiche.Atomic Transactions: Cosmos DB guarantees that database operations performed inside a single stored procedure or trigger are atomic. Di conseguenza, un'applicazione potrà combinare le operazioni correlate in un unico batch, in modo che o tutte o nessuna di esse avranno esito positivo.This lets an application combine related operations in a single batch so that either all of them succeed or none of them succeed.
  • Prestazioni: il mapping intrinseco di JSON al sistema di tipi del linguaggio JavaScript e il fatto che JSON rappresenta anche l'unità di base di archiviazione in Cosmos DB permette di eseguire una serie di ottimizzazioni, tra cui la materializzazione differita dei documenti JSON nel pool di buffer e la loro disponibilità su richiesta per il codice in esecuzione.Performance: The fact that JSON is intrinsically mapped to the Javascript language type system and is also the basic unit of storage in Cosmos DB allows for a number of optimizations like lazy materialization of JSON documents in the buffer pool and making them available on-demand to the executing code. Vi sono altri vantaggi associati all'integrazione della logica di business nel database:There are more performance benefits associated with shipping business logic to the database:

    • Invio in batch: gli sviluppatori possono raggruppare le operazioni, come gli inserimenti, e inviarle in blocco.Batching – Developers can group operations like inserts and submit them in bulk. Ciò comporta una drastica riduzione del costo legato alla latenza del traffico di rete e dei costi generali di archiviazione per la creazione di transazioni separate.The network traffic latency cost and the store overhead to create separate transactions are reduced significantly.
    • Precompilazione: Cosmos DB precompila stored procedure, trigger e funzioni definite dall'utente per evitare il costo della compilazione JavaScript per ogni chiamata.Pre-compilation – Cosmos DB precompiles stored procedures, triggers and user defined functions (UDFs) to avoid JavaScript compilation cost for each invocation. I costi generali di compilazione del codice byte per la logica procedurale vengono ammortizzati a un valore minimo.The overhead of building the byte code for the procedural logic is amortized to a minimal value.
    • Sequenziazione: molte operazioni necessitano di un effetto collaterale ("trigger") che implica potenzialmente l'esecuzione di una o più operazioni di archiviazione secondarie.Sequencing – Many operations need a side-effect (“trigger”) that potentially involves doing one or many secondary store operations. Atomicità a parte, offre prestazioni migliori quando viene passata al server.Aside from atomicity, this is more performant when moved to the server.
  • Incapsulamento: è possibile usare le stored procedure per raggruppare la logica di business in un solo posto.Encapsulation: Stored procedures can be used to group business logic in one place. Ciò comporta due vantaggi:This has two advantages:
    • Aggiunge un livello di astrazione al di sopra dei dati non elaborati, consentendo ai responsabili dell'architettura dati di far evolvere le proprie applicazioni indipendentemente dai dati.It adds an abstraction layer on top of the raw data, which enables data architects to evolve their applications independently from the data. Si tratta di una caratteristica particolarmente vantaggiosa quando i dati sono privi di schema, a causa dei presupposti transitori che potrebbe essere necessario integrare nell'applicazione qualora fosse necessario gestire i dati direttamente.This is particularly advantageous when the data is schema-less, due to the brittle assumptions that may need to be baked into the application if they have to deal with data directly.
    • Questa astrazione consente alle grandi imprese di proteggere i propri dati semplificando l'accesso dagli script.This abstraction lets enterprises keep their data secure by streamlining the access from the scripts.

La creazione e l'esecuzione del trigger di database, stored procedure e gli operatori di query personalizzata è supportata tramite il portale di Azure, API REST, Azure DocumentDB Studio, e client SDK in molte piattaforme, tra cui .NET, Node.js e JavaScript.The creation and execution of database triggers, stored procedure and custom query operators is supported through the Azure portal, the REST API, Azure DocumentDB Studio, and client SDKs in many platforms including .NET, Node.js and JavaScript.

Questa esercitazione usa Node.js SDK con promesse Q per illustrare la sintassi e l'uso di stored procedure, trigger e funzioni definite dall'utente.This tutorial uses the Node.js SDK with Q Promises to illustrate syntax and usage of stored procedures, triggers, and UDFs.

Stored procedureStored procedures

Esempio: scrivere una stored procedure sempliceExample: Write a simple stored procedure

Per cominciare, si analizzerà una semplice stored procedure che restituisce una risposta "Hello World".Let’s start with a simple stored procedure that returns a “Hello World” response.

var helloWorldStoredProc = {
    id: "helloWorld",
    serverScript: function () {
        var context = getContext();
        var response = context.getResponse();

        response.setBody("Hello, World");
    }
}

Le stored procedure vengono registrate per ogni raccolta e funzionano in qualsiasi documento e allegato presente nella raccolta.Stored procedures are registered per collection, and can operate on any document and attachment present in that collection. Nel frammento seguente viene spiegato come registrare la stored procedure helloWorld con una raccolta.The following snippet shows how to register the helloWorld stored procedure with a collection.

// register the stored procedure
var createdStoredProcedure;
client.createStoredProcedureAsync('dbs/testdb/colls/testColl', helloWorldStoredProc)
    .then(function (response) {
        createdStoredProcedure = response.resource;
        console.log("Successfully created stored procedure");
    }, function (error) {
        console.log("Error", error);
    });

Dopo aver registrato la stored procedure è possibile eseguirla a fronte della raccolta e leggere i risultati sul client.Once the stored procedure is registered, we can execute it against the collection, and read the results back at the client.

// execute the stored procedure
client.executeStoredProcedureAsync('dbs/testdb/colls/testColl/sprocs/helloWorld')
    .then(function (response) {
        console.log(response.result); // "Hello, World"
    }, function (err) {
        console.log("Error", error);
    });

L'oggetto contesto offre accesso a tutte le operazioni che è possibile eseguire nelle risorse di archiviazione di Cosmos DB, oltre all'accesso agli oggetti richiesta e risposta.The context object provides access to all operations that can be performed on Cosmos DB storage, as well as access to the request and response objects. In questo caso, è stata usato l'oggetto risposta per impostare il corpo della risposta restituita al client.In this case, we used the response object to set the body of the response that was sent back to the client. Per altre informazioni, vedere la documentazione relativa all'SDK del server JavaScript di Cosmos DB.For more details, refer to the Azure Cosmos DB JavaScript server SDK documentation.

Elaborando ulteriormente questo esempio, è possibile aggiungere alla stored procedure altre funzionalità relative al database.Let us expand on this example and add more database related functionality to the stored procedure. Le stored procedure possono creare, aggiornare, eseguire query ed eliminare documenti e allegati all'interno della raccolta.Stored procedures can create, update, read, query and delete documents and attachments inside the collection.

Esempio: scrivere una stored procedure per creare un documentoExample: Write a stored procedure to create a document

Il frammento successivo mostra come usare l'oggetto contesto per interagire con le risorse di Cosmos DB.The next snippet shows how to use the context object to interact with Cosmos DB resources.

var createDocumentStoredProc = {
    id: "createMyDocument",
    serverScript: function createMyDocument(documentToCreate) {
        var context = getContext();
        var collection = context.getCollection();

        var accepted = collection.createDocument(collection.getSelfLink(),
              documentToCreate,
              function (err, documentCreated) {
                  if (err) throw new Error('Error' + err.message);
                  context.getResponse().setBody(documentCreated.id)
              });
        if (!accepted) return;
    }
}

Questa stored procedure accetta come input documentToCreate, il corpo di un documento da creare nella raccolta corrente.This stored procedure takes as input documentToCreate, the body of a document to be created in the current collection. Tutte queste operazioni sono asincrone e dipendono dai callback della funzione JavaScript.All such operations are asynchronous and depend on JavaScript function callbacks. La funzione di callback ha due parametri: uno per l'oggetto errore in caso di errore dell'operazione e uno per l'oggetto creato.The callback function has two parameters, one for the error object in case the operation fails, and one for the created object. All'interno del callback, gli utenti possono gestire l'eccezione oppure generare un errore.Inside the callback, users can either handle the exception or throw an error. Nel caso in cui non sia disponibile un callback e si verifichi un errore, il runtime di Azure Cosmos DB genera un errore.In case a callback is not provided and there is an error, the Azure Cosmos DB runtime throws an error.

Nell'esempio precedente il callback genera un errore se l'operazione non è riuscita.In the example above, the callback throws an error if the operation failed. In caso contrario, viene impostato l'ID del documento creato come corpo della risposta al client.Otherwise, it sets the id of the created document as the body of the response to the client. Ecco come viene eseguita questa stored procedure con i parametri di input.Here is how this stored procedure is executed with input parameters.

// register the stored procedure
client.createStoredProcedureAsync('dbs/testdb/colls/testColl', createDocumentStoredProc)
    .then(function (response) {
        var createdStoredProcedure = response.resource;

        // run stored procedure to create a document
        var docToCreate = {
            id: "DocFromSproc",
            book: "The Hitchhiker’s Guide to the Galaxy",
            author: "Douglas Adams"
        };

        return client.executeStoredProcedureAsync('dbs/testdb/colls/testColl/sprocs/createMyDocument',
              docToCreate);
    }, function (error) {
        console.log("Error", error);
    })
.then(function (response) {
    console.log(response); // "DocFromSproc"
}, function (error) {
    console.log("Error", error);
});

Notare che è possibile modificare questa stored procedure in modo che accetti una matrice di corpi di documenti come input e possa crearli tutti nell'esecuzione della stessa stored procedure, invece di inviare più richieste di rete per crearle individualmente.Note that this stored procedure can be modified to take an array of document bodies as input and create them all in the same stored procedure execution instead of multiple network requests to create each of them individually. Questo permette di implementare un'efficiente utilità di importazione in blocco per Cosmos DB, di cui si discuterà più avanti in questa esercitazione.This can be used to implement an efficient bulk importer for Cosmos DB (discussed later in this tutorial).

L'esempio descritto ha dimostrato come usare le stored procedure.The example described demonstrated how to use stored procedures. I trigger e le funzioni definite dall'utente (UDF) saranno trattati più avanti in questa esercitazione.We will cover triggers and user defined functions (UDFs) later in the tutorial.

Transazioni del programma del databaseDatabase program transactions

Una transazione in un tipico database può essere definita come una sequenza di operazioni eseguite come singola unità di lavoro logica.Transaction in a typical database can be defined as a sequence of operations performed as a single logical unit of work. Ogni transazione offre garanzie ACID.Each transaction provides ACID guarantees. ACID è un acronimo noto che riassume quattro proprietà: Atomicità, Coerenza, Isolamento e Durabilità.ACID is a well-known acronym that stands for four properties - Atomicity, Consistency, Isolation and Durability.

In breve, l'atomicità garantisce che tutte le operazioni eseguite nell'ambito di una transazione siano trattate come unità singola e che venga eseguito il commit di tutte le operazioni o di nessuna.Briefly, atomicity guarantees that all the work done inside a transaction is treated as a single unit where either all of it is committed or none. La coerenza garantisce che i dati siano sempre in ottimo stato interno in tutte le transazioni.Consistency makes sure that the data is always in a good internal state across transactions. L'isolamento garantisce che non vi siano transazioni conflittuali; in generale, la maggior parte dei sistemi commerciali offre più livelli di isolamento utilizzabili in base alle esigenze dell'applicazione.Isolation guarantees that no two transactions interfere with each other – generally, most commercial systems provide multiple isolation levels that can be used based on the application needs. La durabilità assicura che qualsiasi modifica di cui sia stato eseguito il commit nel database sia sempre presente.Durability ensures that any change that’s committed in the database will always be present.

JavaScript in Cosmos DB è ospitato nello stesso spazio di memoria del database.In Cosmos DB, JavaScript is hosted in the same memory space as the database. Di conseguenza, le richieste effettuate nell'ambito delle stored procedure e dei trigger vengono eseguite nello stesso ambito di una sessione di database.Hence, requests made within stored procedures and triggers execute in the same scope of a database session. In questo modo Cosmos DB può garantire proprietà ACID per tutte le transazioni che fanno parte di una singola stored procedure o un unico trigger.This enables Cosmos DB to guarantee ACID for all operations that are part of a single stored procedure/trigger. Considerare la definizione della stored procedure seguente:Consider the following stored procedure definition:

// JavaScript source code
var exchangeItemsSproc = {
    id: "exchangeItems",
    serverScript: function (playerId1, playerId2) {
        var context = getContext();
        var collection = context.getCollection();
        var response = context.getResponse();

        var player1Document, player2Document;

        // query for players
        var filterQuery = 'SELECT * FROM Players p where p.id  = "' + playerId1 + '"';
        var accept = collection.queryDocuments(collection.getSelfLink(), filterQuery, {},
            function (err, documents, responseOptions) {
                if (err) throw new Error("Error" + err.message);

                if (documents.length != 1) throw "Unable to find both names";
                player1Document = documents[0];

                var filterQuery2 = 'SELECT * FROM Players p where p.id = "' + playerId2 + '"';
                var accept2 = collection.queryDocuments(collection.getSelfLink(), filterQuery2, {},
                    function (err2, documents2, responseOptions2) {
                        if (err2) throw new Error("Error" + err2.message);
                        if (documents2.length != 1) throw "Unable to find both names";
                        player2Document = documents2[0];
                        swapItems(player1Document, player2Document);
                        return;
                    });
                if (!accept2) throw "Unable to read player details, abort ";
            });

        if (!accept) throw "Unable to read player details, abort ";

        // swap the two players’ items
        function swapItems(player1, player2) {
            var player1ItemSave = player1.item;
            player1.item = player2.item;
            player2.item = player1ItemSave;

            var accept = collection.replaceDocument(player1._self, player1,
                function (err, docReplaced) {
                    if (err) throw "Unable to update player 1, abort ";

                    var accept2 = collection.replaceDocument(player2._self, player2,
                        function (err2, docReplaced2) {
                            if (err) throw "Unable to update player 2, abort"
                        });

                    if (!accept2) throw "Unable to update player 2, abort";
                });

            if (!accept) throw "Unable to update player 1, abort";
        }
    }
}

// register the stored procedure in Node.js client
client.createStoredProcedureAsync(collection._self, exchangeItemsSproc)
    .then(function (response) {
        var createdStoredProcedure = response.resource;
    }
);

Questa stored procedure usa le transazioni in un'applicazione di gioco per scambiare elementi tra due giocatori in un'unica operazione.This stored procedure uses transactions within a gaming app to trade items between two players in a single operation. La stored procedure prova a leggere due documenti, ciascuno corrispondente all'ID del giocatore passato come argomento.The stored procedure attempts to read two documents each corresponding to the player IDs passed in as an argument. Se vengono trovati i documenti di entrambi i giocatori, la stored procedure aggiorna i documenti scambiando gli elementi.If both player documents are found, then the stored procedure updates the documents by swapping their items. Se si verificano errori lungo il percorso, viene generata un'eccezione JavaScript che interrompe implicitamente la transazione.If any errors are encountered along the way, it throws a JavaScript exception that implicitly aborts the transaction.

Se la stored procedure della raccolta è registrata in una raccolta a partizione singola, la transazione ha come ambito tutti i documenti all'interno della raccolta.If the collection the stored procedure is registered against is a single-partition collection, then the transaction is scoped to all the documents within the collection. Se la raccolta è partizionata, le stored procedure vengono eseguite nell'ambito della transazione di una singola chiave di partizione.If the collection is partitioned, then stored procedures are executed in the transaction scope of a single partition key. Ogni esecuzione di stored procedure deve quindi includere un valore di chiave di partizione corrispondente all'ambito in cui la transazione deve essere eseguita.Each stored procedure execution must then include a partition key value corresponding to the scope the transaction must run under. Per altri dettagli, vedere l'articolo relativo al partizionamento di Azure Cosmos DB.For more details, see Azure Cosmos DB Partitioning.

Commit e rollbackCommit and rollback

Le transazioni sono integrate in maniera approfondita e nativa nel modello di programmazione JavaScript di Cosmos DB.Transactions are deeply and natively integrated into Cosmos DB’s JavaScript programming model. All'interno di una funzione JavaScript, viene eseguito il wrapping di tutte le operazioni in un'unica transazione.Inside a JavaScript function, all operations are automatically wrapped under a single transaction. Se la funzione JavaScript viene completata senza eccezioni, viene eseguito il commit delle operazioni nel database.If the JavaScript completes without any exception, the operations to the database are committed. Le istruzioni "BEGIN TRANSACTION" e "COMMIT TRANSACTION" nei database relazionali sono implicite in Cosmos DB.In effect, the “BEGIN TRANSACTION” and “COMMIT TRANSACTION” statements in relational databases are implicit in Cosmos DB.

Se si verifica un'eccezione qualsiasi che viene propagata dallo script, il runtime JavaScript di Cosmos DB esegue il rollback dell'intera transazione.If there is any exception that’s propagated from the script, Cosmos DB’s JavaScript runtime will roll back the whole transaction. Come illustrato in un esempio precedente, la generazione di un'eccezione equivale effettivamente a un'istruzione "ROLLBACK TRANSACTION" in Cosmos DB.As shown in the earlier example, throwing an exception is effectively equivalent to a “ROLLBACK TRANSACTION” in Cosmos DB.

Coerenza dei datiData consistency

Le stored procedure e i trigger vengono sempre eseguiti sulla cartella di replica principale del contenitore di Azure Cosmos DB.Stored procedures and triggers are always executed on the primary replica of the Azure Cosmos DB container. In tal modo si garantisce la coerenza assoluta delle letture all'interno delle stored procedure.This ensures that reads from inside stored procedures offer strong consistency. È possibile eseguire le query che usano funzioni definite dall'utente sulla replica principale o in qualsiasi replica secondaria, ma è necessario assicurarsi di soddisfare il livello di coerenza richiesto scegliendo la replica appropriata.Queries using user defined functions can be executed on the primary or any secondary replica, but we ensure to meet the requested consistency level by choosing the appropriate replica.

Esecuzione vincolataBounded execution

Tutte le operazioni di Cosmos DB devono essere completate entro la scadenza specificata dal server.All Cosmos DB operations must complete within the server specified request timeout duration. Questo vincolo si applica anche alle funzioni JavaScript (stored procedure, trigger e funzioni definite dall'utente).This constraint also applies to JavaScript functions (stored procedures, triggers and user-defined functions). Se un'operazione non viene completata entro questo limite di tempo, viene eseguito il rollback della transazione.If an operation does not complete with that time limit, the transaction is rolled back. Le funzioni JavaScript devono terminare entro il tempo limite oppure implementare un modello basato sulla continuazione in modo da riprendere l'esecuzione o eseguirla in batch.JavaScript functions must finish within the time limit or implement a continuation based model to batch/resume execution.

Per semplificare lo sviluppo delle stored procedure e dei trigger per la gestione dei limiti di tempo, tutte le funzioni nell'oggetto raccolta (per creare, leggere, sostituire ed eliminare i documenti e gli allegati) restituiscono un valore booleano che indica se l'operazione verrà completata.In order to simplify development of stored procedures and triggers to handle time limits, all functions under the collection object (for create, read, replace, and delete of documents and attachments) return a Boolean value that represents whether that operation will complete. Se questo valore è falso, sarà indice che il tempo limite sta per scadere e che è necessario concludere l'esecuzione della procedura.If this value is false, it is an indication that the time limit is about to expire and that the procedure must wrap up execution. Il completamento delle operazioni inserite in coda precedentemente alla prima operazione di archiviazione non accettata è garantito se la stored procedure viene completata in tempo e non vengono inserite in coda altre richieste.Operations queued prior to the first unaccepted store operation are guaranteed to complete if the stored procedure completes in time and does not queue any more requests.

Anche le funzioni JavaScript sono vincolate al consumo di risorse.JavaScript functions are also bounded on resource consumption. Cosmos DB riserva una velocità effettiva per ogni raccolta in base alle dimensioni dell'account di database di cui è stato effettuato il provisioning.Cosmos DB reserves throughput per collection based on the provisioned size of a database account. La velocità effettiva viene espressa in termini di un'unità normalizzata di consumo CPU, memoria e IO, denominata unità di richiesta, o RU.Throughput is expressed in terms of a normalized unit of CPU, memory and IO consumption called request units or RUs. Le funzioni JavaScript possono potenzialmente usare un numero elevato di RU in breve tempo; per tale motivo, è possibile che venga limitata la frequenza del traffico di rete quando si raggiunge il limite della raccolta.JavaScript functions can potentially use up a large number of RUs within a short time, and might get rate-limited if the collection’s limit is reached. È anche possibile che le stored procedure che richiedono un utilizzo elevato di risorse vengano messe in quarantena per assicurare la disponibilità delle operazioni di database primitive.Resource intensive stored procedures might also be quarantined to ensure availability of primitive database operations.

Esempio: importazione in blocco dei dati in un programma di databaseExample: Bulk importing data into a database program

Di seguito è riportato un esempio di stored procedure scritta per importare in blocco i documenti in una raccolta.Below is an example of a stored procedure that is written to bulk-import documents into a collection. Da notare il modo in cui la stored procedure gestisce l'esecuzione vincolata verificando il valore booleano restituito da createDocument e quindi usa il numero di documenti inseriti in ogni chiamata della stored procedure per tracciare e riprendere l'avanzamento nei vari batch.Note how the stored procedure handles bounded execution by checking the Boolean return value from createDocument, and then uses the count of documents inserted in each invocation of the stored procedure to track and resume progress across batches.

function bulkImport(docs) {
    var collection = getContext().getCollection();
    var collectionLink = collection.getSelfLink();

    // The count of imported docs, also used as current doc index.
    var count = 0;

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

    var docsLength = docs.length;
    if (docsLength == 0) {
        getContext().getResponse().setBody(0);
    }

    // Call the create API to create a document.
    tryCreate(docs[count], callback);

    // Note that there are 2 exit conditions:
    // 1) The createDocument request was not accepted. 
    //    In this case the callback will not be called, we just call setBody and we are done.
    // 2) The callback was called docs.length times.
    //    In this case all documents were created and we don’t need to call tryCreate anymore. Just call setBody and we are done.
    function tryCreate(doc, callback) {
        var isAccepted = collection.createDocument(collectionLink, doc, callback);

        // If the request was accepted, callback will be called.
        // Otherwise report current count back to the client, 
        // which will call the script again with remaining set of docs.
        if (!isAccepted) getContext().getResponse().setBody(count);
    }

    // This is called when collection.createDocument is done in order to process the result.
    function callback(err, doc, options) {
        if (err) throw err;

        // One more document has been inserted, increment the count.
        count++;

        if (count >= docsLength) {
            // If we created all documents, we are done. Just set the response.
            getContext().getResponse().setBody(count);
        } else {
            // Create next document.
            tryCreate(docs[count], callback);
        }
    }
}

Trigger del databaseDatabase triggers

Pre-trigger del databaseDatabase pre-triggers

Cosmos DB include trigger che vengono eseguiti o attivati da un'operazione su un documento.Cosmos DB provides triggers that are executed or triggered by an operation on a document. Ad esempio, quando si crea un documento è possibile specificare un pre-trigger, che verrà eseguito prima della creazione.For example, you can specify a pre-trigger when you are creating a document – this pre-trigger will run before the document is created. Di seguito è riportato un esempio di come è possibile usare i pre-trigger per convalidare le proprietà di un documento in corso di creazione:The following is an example of how pre-triggers can be used to validate the properties of a document that is being created:

var validateDocumentContentsTrigger = {
    id: "validateDocumentContents",
    serverScript: function validate() {
        var context = getContext();
        var request = context.getRequest();

        // document to be created in the current operation
        var documentToCreate = request.getBody();

        // validate properties
        if (!("timestamp" in documentToCreate)) {
            var ts = new Date();
            documentToCreate["my timestamp"] = ts.getTime();
        }

        // update the document that will be created
        request.setBody(documentToCreate);
    },
    triggerType: TriggerType.Pre,
    triggerOperation: TriggerOperation.Create
}

E il corrispondente codice di registrazione lato client di Node.js per il trigger:And the corresponding Node.js client-side registration code for the trigger:

// register pre-trigger
client.createTriggerAsync(collection.self, validateDocumentContentsTrigger)
    .then(function (response) {
        console.log("Created", response.resource);
        var docToCreate = {
            id: "DocWithTrigger",
            event: "Error",
            source: "Network outage"
        };

        // run trigger while creating above document 
        var options = { preTriggerInclude: "validateDocumentContents" };

        return client.createDocumentAsync(collection.self,
              docToCreate, options);
    }, function (error) {
        console.log("Error", error);
    })
.then(function (response) {
    console.log(response.resource); // document with timestamp property added
}, function (error) {
    console.log("Error", error);
});

I pre-trigger non possono avere parametri di input.Pre-triggers cannot have any input parameters. L'oggetto richiesta può essere usato per gestire il messaggio di richiesta associato all'operazione.The request object can be used to manipulate the request message associated with the operation. In questo caso, si esegue il pre-trigger preliminare contemporaneamente alla creazione di un documento e il corpo del messaggio di richiesta contiene il documento da creare in formato JSON.Here, the pre-trigger is being run with the creation of a document, and the request message body contains the document to be created in JSON format.

Quando i trigger vengono registrati, gli utenti possono specificare le operazioni con le quali è possibile eseguirli.When triggers are registered, users can specify the operations that it can run with. Questo trigger è stato creato con TriggerOperation.Create, quindi quanto riportato di seguito non è consentito.This trigger was created with TriggerOperation.Create, which means the following is not permitted.

var options = { preTriggerInclude: "validateDocumentContents" };

client.replaceDocumentAsync(docToReplace.self,
              newDocBody, options)
.then(function (response) {
    console.log(response.resource);
}, function (error) {
    console.log("Error", error);
});

// Fails, can’t use a create trigger in a replace operation

Post-trigger del databaseDatabase post-triggers

I post-trigger, come i pre-trigger, sono associati a un'operazione su un documento e non accettano parametri di input.Post-triggers, like pre-triggers, are associated with an operation on a document and don’t take any input parameters. Vengono eseguiti dopo il completamento dell'operazione e hanno accesso al messaggio di risposta inviato al client.They run after the operation has completed, and have access to the response message that is sent to the client.

Nell'esempio seguente vengono illustrati i post-trigger in azione:The following example shows post-triggers in action:

var updateMetadataTrigger = {
    id: "updateMetadata",
    serverScript: function updateMetadata() {
        var context = getContext();
        var collection = context.getCollection();
        var response = context.getResponse();

        // document that was created
        var createdDocument = response.getBody();

        // query for metadata document
        var filterQuery = 'SELECT * FROM root r WHERE r.id = "_metadata"';
        var accept = collection.queryDocuments(collection.getSelfLink(), filterQuery,
            updateMetadataCallback);
        if(!accept) throw "Unable to update metadata, abort";

        function updateMetadataCallback(err, documents, responseOptions) {
            if(err) throw new Error("Error" + err.message);
                     if(documents.length != 1) throw 'Unable to find metadata document';

                     var metadataDocument = documents[0];

                     // update metadata
                     metadataDocument.createdDocuments += 1;
                     metadataDocument.createdNames += " " + createdDocument.id;
                     var accept = collection.replaceDocument(metadataDocument._self,
                           metadataDocument, function(err, docReplaced) {
                                  if(err) throw "Unable to update metadata, abort";
                           });
                     if(!accept) throw "Unable to update metadata, abort";
                     return;                    
        }                                                                                            
    },
    triggerType: TriggerType.Post,
    triggerOperation: TriggerOperation.All
}

È possibile registrare un trigger come illustrato nell'esempio seguente.The trigger can be registered as shown in the following sample.

// register post-trigger
client.createTriggerAsync('dbs/testdb/colls/testColl', updateMetadataTrigger)
    .then(function(createdTrigger) { 
        var docToCreate = { 
            name: "artist_profile_1023",
            artist: "The Band",
            albums: ["Hellujah", "Rotators", "Spinning Top"]
        };

        // run trigger while creating above document 
        var options = { postTriggerInclude: "updateMetadata" };

        return client.createDocumentAsync(collection.self,
              docToCreate, options);
    }, function(error) {
        console.log("Error" , error);
    })
.then(function(response) {
    console.log(response.resource); 
}, function(error) {
    console.log("Error" , error);
});

Il trigger esegue query sul documento dei metadati, aggiornandolo con le informazioni relative al documento appena creato.This trigger queries for the metadata document and updates it with details about the newly created document.

Un aspetto importante da tenere presente è l'esecuzione transazionale dei trigger in Cosmos DB.One thing that is important to note is the transactional execution of triggers in Cosmos DB. Questo post-trigger viene eseguito come parte della stessa transazione relativa alla creazione del documento originale.This post-trigger runs as part of the same transaction as the creation of the original document. Pertanto, se si genera un'eccezione dal post-trigger (ad esempio se non è possibile aggiornare il documento dei metadati), l'intera transazione avrà esito negativo e verrà ripristinata allo stato precedente.Therefore, if we throw an exception from the post-trigger (say if we are unable to update the metadata document), the whole transaction will fail and be rolled back. Non verrà creato alcun documento e verrà restituita un'eccezione.No document will be created, and an exception will be returned.

Funzioni definite dall'utenteUser-defined functions

Funzioni definite dall'utente (UDF) vengono utilizzate per estendere la grammatica del linguaggio di query SQL del database Cosmos Azure e implementare la logica di business personalizzata.User-defined functions (UDFs) are used to extend the Azure Cosmos DB SQL query language grammar and implement custom business logic. Possono essere richiamate solo dall'interno delle query.They can only be called from inside queries. Non hanno accesso all'oggetto contesto e vanno usate come JavaScript di solo calcolo.They do not have access to the context object and are meant to be used as compute-only JavaScript. È quindi possibile eseguire le funzioni definite dall'utente su repliche secondarie del servizio Cosmos DB.Therefore, UDFs can be run on secondary replicas of the Cosmos DB service.

L'esempio seguente consente di creare una funzione definita dall'utente per calcolare l'imposta sul reddito in base ai tassi relativi a varie fasce di reddito. La funzione viene quindi usata all'interno di una query per trovare tutte le persone che hanno pagato oltre 20.000 dollari di imposte.The following sample creates a UDF to calculate income tax based on rates for various income brackets, and then uses it inside a query to find all people who paid more than $20,000 in taxes.

var taxUdf = {
    id: "tax",
    serverScript: function tax(income) {

        if(income == undefined) 
            throw 'no input';

        if (income < 1000) 
            return income * 0.1;
        else if (income < 10000) 
            return income * 0.2;
        else
            return income * 0.4;
    }
}

La funzione UDF può in seguito essere usata in query come quella riportata nell'esempio seguente:The UDF can subsequently be used in queries like in the following sample:

// register UDF
client.createUserDefinedFunctionAsync('dbs/testdb/colls/testColl', taxUdf)
    .then(function(response) { 
        console.log("Created", response.resource);

        var query = 'SELECT * FROM TaxPayers t WHERE udf.tax(t.income) > 20000'; 
        return client.queryDocuments('dbs/testdb/colls/testColl',
               query).toArrayAsync();
    }, function(error) {
        console.log("Error" , error);
    })
.then(function(response) {
    var documents = response.feed;
    console.log(response.resource); 
}, function(error) {
    console.log("Error" , error);
});

API della Language-Integrated Query di JavaScriptJavaScript language-integrated query API

Oltre a eseguire una query utilizzando la grammatica SQL di Azure Cosmos DB, il SDK lato server consente di eseguire query ottimizzate attraverso un'interfaccia intuitiva di JavaScript senza la conoscenza di SQL.In addition to issuing queries using Azure Cosmos DB's SQL grammar, the server-side SDK allows you to perform optimized queries using a fluent JavaScript interface without any knowledge of SQL. L'API della query JavaScript consente di creare query a livello di programmazione passando funzioni predicate in chiamate di funzione concatenabili, con una sintassi familiare alle librerie JavaScript predefinite e diffuse della matrice ECMAScript5 come lodash.The JavaScript query API allows you to programmatically build queries by passing predicate functions into chainable function calls, with a syntax familiar to ECMAScript5's Array built-ins and popular JavaScript libraries like lodash. Le query vengono analizzate dal runtime JavaScript per essere eseguite in modo efficiente usando gli indici di Azure Cosmos DB.Queries are parsed by the JavaScript runtime to be executed efficiently using Azure Cosmos DB’s indices.

Nota

__ (doppio carattere di sottolineatura) è un alias per getContext().getCollection().__ (double-underscore) is an alias to getContext().getCollection().
Per accedere all'API della query JavaScript, in altre parole, è possibile utilizzare __ o getContext().getCollection().In other words, you can use __ or getContext().getCollection() to access the JavaScript query API.

Tra le funzioni supportate:Supported functions include:

  • chain() ... .value([callback] [, options]) chain() ... .value([callback] [, options])
    • Avvia una chiamata concatenata che deve terminare con value().Starts a chained call which must be terminated with value().
  • filter(predicateFunction [, options] [, callback]) filter(predicateFunction [, options] [, callback])
    • Filtra l'input usando una funzione predicato che restituisce true o false per includere o escludere i documenti di input dal set risultante.Filters the input using a predicate function which returns true/false in order to filter in/out input documents into the resulting set. Il comportamento è simile a quello di una clausola WHERE in SQL.This behaves similar to a WHERE clause in SQL.
  • map(transformationFunction [, options] [, callback]) map(transformationFunction [, options] [, callback])
    • Applica una proiezione a partire da una funzione di trasformazione che esegue il mapping di ogni elemento di input a un valore o oggetto JavaScript.Applies a projection given a transformation function which maps each input item to a JavaScript object or value. Il comportamento è simile a quello di una clausola SELECT in SQL.This behaves similar to a SELECT clause in SQL.
  • pluck([propertyName] [, options] [, callback]) pluck([propertyName] [, options] [, callback])
    • Collegamento a una mappa che consente di estrarre il valore di una singola proprietà da ogni elemento di input.This is a shortcut for a map which extracts the value of a single property from each input item.
  • flatten([isShallow] [, options] [, callback]) flatten([isShallow] [, options] [, callback])
    • Combina e appiattisce le matrici da ogni elemento di input in un'unica matrice.Combines and flattens arrays from each input item in to a single array. Il comportamento è simile a quello di SelectMany in LINQ.This behaves similar to SelectMany in LINQ.
  • sortBy([predicate] [, options] [, callback]) sortBy([predicate] [, options] [, callback])
    • Produce un nuovo set di documenti ordinandoli nel flusso di documenti di input in ordine crescente usando il predicato specificato.Produce a new set of documents by sorting the documents in the input document stream in ascending order using the given predicate. Il comportamento è simile a quello di una clausola ORDER BY in SQL.This behaves similar to a ORDER BY clause in SQL.
  • sortByDescending([predicate] [, options] [, callback]) sortByDescending([predicate] [, options] [, callback])
    • Produce un nuovo set di documenti ordinandoli nel flusso di documenti di input in ordine decrescente usando il predicato specificato.Produce a new set of documents by sorting the documents in the input document stream in descending order using the given predicate. Il comportamento è simile a quello di una clausola ORDER BY x DESC in SQL.This behaves similar to a ORDER BY x DESC clause in SQL.

Quando inclusi all'interno delle funzioni predicato e/o selettore, i seguenti costrutti JavaScript vengono automaticamente ottimizzati per l'esecuzione diretta sugli indici di Azure Cosmos DB:When included inside predicate and/or selector functions, the following JavaScript constructs get automatically optimized to run directly on Azure Cosmos DB indices:

  • Operatori semplici: = + - * / % | ^ & == != === !=== < > <= >= || && << >> >>>!Simple operators: = + - * / % | ^ & == != === !=== < > <= >= || && << >> >>>! ~
  • Valori letterali, incluso il valore letterale dell'oggetto: {}Literals, including the object literal: {}
  • var, returnvar, return

I seguenti costrutti JavaScript non vengono ottimizzati per gli indici di Azure Cosmos DB:The following JavaScript constructs do not get optimized for Azure Cosmos DB indices:

  • Flusso di controllo (ad esempio, se, per, mentre)Control flow (e.g. if, for, while)
  • Chiamate di funzioneFunction calls

Per ulteriori informazioni, vedere Server-Side JSDocs.For more information, please see our Server-Side JSDocs.

Esempio: Scrivere una stored procedure usando l'API di query JavaScriptExample: Write a stored procedure using the JavaScript query API

L'esempio di codice seguente illustra come usare l'API Query JavaScript nel contesto di una stored procedure.The following code sample is an example of how the JavaScript Query API can be used in the context of a stored procedure. La stored procedure inserisce un documento, fornito da un parametro di input, e aggiorna un documento di metadati, usando il metodo __.filter() , con minSize, maxSize e totalSize in base alla proprietà relativa alle dimensioni del documento di input.The stored procedure inserts a document, given by an input parameter, and updates a metadata document, using the __.filter() method, with minSize, maxSize, and totalSize based upon the input document's size property.

/**
 * Insert actual doc and update metadata doc: minSize, maxSize, totalSize based on doc.size.
 */
function insertDocumentAndUpdateMetadata(doc) {
  // HTTP error codes sent to our callback funciton by DocDB server.
  var ErrorCode = {
    RETRY_WITH: 449,
  }

  var isAccepted = __.createDocument(__.getSelfLink(), doc, {}, function(err, doc, options) {
    if (err) throw err;

    // Check the doc (ignore docs with invalid/zero size and metaDoc itself) and call updateMetadata.
    if (!doc.isMetadata && doc.size > 0) {
      // Get the meta document. We keep it in the same collection. it's the only doc that has .isMetadata = true.
      var result = __.filter(function(x) {
        return x.isMetadata === true
      }, function(err, feed, options) {
        if (err) throw err;

        // We assume that metadata doc was pre-created and must exist when this script is called.
        if (!feed || !feed.length) throw new Error("Failed to find the metadata document.");

        // The metadata document.
        var metaDoc = feed[0];

        // Update metaDoc.minSize:
        // for 1st document use doc.Size, for all the rest see if it's less than last min.
        if (metaDoc.minSize == 0) metaDoc.minSize = doc.size;
        else metaDoc.minSize = Math.min(metaDoc.minSize, doc.size);

        // Update metaDoc.maxSize.
        metaDoc.maxSize = Math.max(metaDoc.maxSize, doc.size);

        // Update metaDoc.totalSize.
        metaDoc.totalSize += doc.size;

        // Update/replace the metadata document in the store.
        var isAccepted = __.replaceDocument(metaDoc._self, metaDoc, function(err) {
          if (err) throw err;
          // Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again 
          //       and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).
          //       We have to take care of that on the client side.
        });
        if (!isAccepted) throw new Error("replaceDocument(metaDoc) returned false.");
      });
      if (!result.isAccepted) throw new Error("filter for metaDoc returned false.");
    }
  });
  if (!isAccepted) throw new Error("createDocument(actual doc) returned false.");
}

Foglio riassuntivo di SQL per JavaScriptSQL to Javascript cheat sheet

Nella tabella seguente vengono presentate varie query SQL e le query JavaScript corrispondenti.The following table presents various SQL queries and the corresponding JavaScript queries.

Come le query SQL, le chiavi di proprietà del documento (ad esempio doc.id) fanno distinzione tra maiuscole e minuscole.As with SQL queries, document property keys (e.g. doc.id) are case-sensitive.

SQLSQL API di query JavaScriptJavaScript Query API Descrizione sottoDescription below
SELECT *SELECT *
FROM docsFROM docs
.map(function(doc) {.map(function(doc) {
    return doc;    return doc;
});});
11
SELECT docs.id, docs.message AS msg, docs.actionsSELECT docs.id, docs.message AS msg, docs.actions
FROM docsFROM docs
.map(function(doc) {.map(function(doc) {
    return {    return {
         id: doc.id,        id: doc.id,
         msg: doc.message,        msg: doc.message,
         actions:doc.actions        actions:doc.actions
    };    };
});});
22
SELECT *SELECT *
FROM docsFROM docs
WHERE docs.id="X998_Y998"WHERE docs.id="X998_Y998"
.filter(function(doc) {.filter(function(doc) {
    return doc.id ==="X998_Y998";    return doc.id ==="X998_Y998";
});});
33
SELECT *SELECT *
FROM docsFROM docs
WHERE ARRAY_CONTAINS(docs.Tags, 123)WHERE ARRAY_CONTAINS(docs.Tags, 123)
.filter(function(x) {.filter(function(x) {
    return x.Tags && x.Tags.indexOf(123) > -1;    return x.Tags && x.Tags.indexOf(123) > -1;
});});
44
SELECT docs.id, docs.message AS msgSELECT docs.id, docs.message AS msg
FROM docsFROM docs
WHERE docs.id="X998_Y998"WHERE docs.id="X998_Y998"
.chain().chain()
    .filter(function(doc) {    .filter(function(doc) {
        return doc.id ==="X998_Y998";        return doc.id ==="X998_Y998";
    })    })
    .map(function(doc) {    .map(function(doc) {
       return {       return {
             id: doc.id,            id: doc.id,
             msg: doc.message            msg: doc.message
       };       };
    })    })
.value();.value();
55
SELECT VALUE tagSELECT VALUE tag
FROM docsFROM docs
JOIN tag IN docs.TagsJOIN tag IN docs.Tags
ORDER BY docs._tsORDER BY docs._ts
.chain().chain()
    .filter(function(doc) {    .filter(function(doc) {
         return doc.Tags && Array.isArray(doc.Tags);        return doc.Tags && Array.isArray(doc.Tags);
    })    })
    .sortBy(function(doc) {    .sortBy(function(doc) {
        return doc._ts;        return doc._ts;
    })    })
    .pluck("Tags")    .pluck("Tags")
    .flatten()    .flatten()
    .value()    .value()
66

Le descrizioni seguenti illustrano ogni query nella tabella sopra.The following descriptions explain each query in the table above.

  1. Viene restituita così com'è in tutti i documenti, impaginati con token di continuazione.Results in all documents (paginated with continuation token) as is.
  2. Proietta l'ID, il messaggio (con aliasing effettuato a msg) e l'azione da tutti i documenti.Projects the id, message (aliased to msg), and action from all documents.
  3. Esegue una query sui documenti con il predicato: id = "X998_Y998".Queries for documents with the predicate: id = "X998_Y998".
  4. Esegue una query sui documenti che hanno una proprietà Tags e Tags è una matrice che contiene il valore 123.Queries for documents that have a Tags property and Tags is an array containing the value 123.
  5. Esegue una query sui documenti con un predicato id = "X998_Y998" e quindi proietta l'ID e il messaggio (con aliasing effettuato a msg).Queries for documents with a predicate, id = "X998_Y998", and then projects the id and message (aliased to msg).
  6. Filtra i documenti che hanno la proprietà di matrice Tags, ordina i documenti risultanti in base alla proprietà di sistema timestamp _ts e quindi proietta e appiattisce la matrice Tags.Filters for documents which have an array property, Tags, and sorts the resulting documents by the _ts timestamp system property, and then projects + flattens the Tags array.

Supporto di runtimeRuntime support

Il database di Azure Cosmos API sul lato di JavaScript server fornisce il supporto per la maggior parte delle funzionalità del linguaggio JavaScript mainstream come standard da ECMA-262.The Azure Cosmos DB JavaScript server side API provides support for the most of the mainstream JavaScript language features as standardized by ECMA-262.

SicurezzaSecurity

Le stored procedure e i trigger di JavaScript vengono create in modalità sandbox in modo che gli effetti di un unico script non vengano trasferiti all'altro senza che siano stati prima sottoposti all'isolamento delle transazioni snapshot a livello di database.JavaScript stored procedures and triggers are sandboxed so that the effects of one script do not leak to the other without going through the snapshot transaction isolation at the database level. Gli ambienti di runtime vengono riuniti in pool, ma ripuliti dal contesto dopo ciascuna esecuzione.The runtime environments are pooled but cleaned of the context after each run. Di conseguenza è possibile garantirne la sicurezza rispetto a effetti collaterali imprevisti causati l'un l'altro.Hence they are guaranteed to be safe of any unintended side effects from each other.

PrecompilazionePre-compilation

Le stored procedure, i trigger e le UDF vengono precompilate implicitamente nel formato di codice byte per evitare i costi di compilazione ad ogni chiamata dello script.Stored procedures, triggers and UDFs are implicitly precompiled to the byte code format in order to avoid compilation cost at the time of each script invocation. Questo garantisce la velocità elevata e il footprint ridotto delle chiamate delle stored procedure.This ensures invocations of stored procedures are fast and have a low footprint.

Supporto di client SDKClient SDK support

Oltre ai database Azure Cosmos Node.js API, Azure Cosmos DB è .NET, .NET Core, Java, JavaScript , e Python SDK per anche l'API di SQL.In addition to the Azure Cosmos DB Node.js API, Azure Cosmos DB has .NET, .NET Core, Java, JavaScript, and Python SDKs for the SQL API as well. È possibile creare ed eseguire stored procedure, trigger e UDFs usando anche uno qualsiasi di questi SDK.Stored procedures, triggers and UDFs can be created and executed using any of these SDKs as well. Nell'esempio seguente viene illustrato come creare ed eseguire una stored procedure con il client .NET.The following example shows how to create and execute a stored procedure using the .NET client. Notare il modo in cui i tipi -NET vengono passati nella stored procedure come JSON e poi riletti.Note how the .NET types are passed into the stored procedure as JSON and read back.

var markAntiquesSproc = new StoredProcedure
{
    Id = "ValidateDocumentAge",
    Body = @"
            function(docToCreate, antiqueYear) {
                var collection = getContext().getCollection();    
                var response = getContext().getResponse();    

                if(docToCreate.Year != undefined && docToCreate.Year < antiqueYear){
                    docToCreate.antique = true;
                }

                collection.createDocument(collection.getSelfLink(), docToCreate, {}, 
                    function(err, docCreated, options) { 
                        if(err) throw new Error('Error while creating document: ' + err.message);                              
                        if(options.maxCollectionSizeInMb == 0) throw 'max collection size not found'; 
                        response.setBody(docCreated);
                });
         }"
};

// register stored procedure
StoredProcedure createdStoredProcedure = await client.CreateStoredProcedureAsync(UriFactory.CreateDocumentCollectionUri("db", "coll"), markAntiquesSproc);
dynamic document = new Document() { Id = "Borges_112" };
document.Title = "Aleph";
document.Year = 1949;

// execute stored procedure
Document createdDocument = await client.ExecuteStoredProcedureAsync<Document>(UriFactory.CreateStoredProcedureUri("db", "coll", "ValidateDocumentAge"), document, 1920);

In questo esempio viene illustrato come utilizzare il API .NET SQL per creare un pre- trigger di e creare un documento con il trigger abilitato.This sample shows how to use the SQL .NET API to create a pre-trigger and create a document with the trigger enabled.

Trigger preTrigger = new Trigger()
{
    Id = "CapitalizeName",
    Body = @"function() {
        var item = getContext().getRequest().getBody();
        item.id = item.id.toUpperCase();
        getContext().getRequest().setBody(item);
    }",
    TriggerOperation = TriggerOperation.Create,
    TriggerType = TriggerType.Pre
};

Document createdItem = await client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri("db", "coll"), new Document { Id = "documentdb" },
    new RequestOptions
    {
        PreTriggerInclude = new List<string> { "CapitalizeName" },
    });

E l'esempio seguente viene illustrato come creare una funzione definita dall'utente (UDF) e utilizzarlo in un query SQL.And the following example shows how to create a user defined function (UDF) and use it in a SQL query.

UserDefinedFunction function = new UserDefinedFunction()
{
    Id = "LOWER",
    Body = @"function(input) 
    {
        return input.toLowerCase();
    }"
};

foreach (Book book in client.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri("db", "coll"),
    "SELECT * FROM Books b WHERE udf.LOWER(b.Title) = 'war and peace'"))
{
    Console.WriteLine("Read {0} from query", book);
}

API RESTREST API

Tutte le operazioni di Azure Cosmos DB possono essere eseguite in modalità RESTful.All Azure Cosmos DB operations can be performed in a RESTful manner. È possibile registrare stored procedure, trigger e funzioni definite dall'utente in una raccolta usando il verbo HTTP POST.Stored procedures, triggers and user-defined functions can be registered under a collection by using HTTP POST. Di seguito è riportato un esempio di come registrare una stored procedure:The following is an example of how to register a stored procedure:

POST https://<url>/sprocs/ HTTP/1.1
authorization: <<auth>>
x-ms-date: Thu, 07 Aug 2014 03:43:10 GMT


var x = {
  "name": "createAndAddProperty",
  "body": function (docToCreate, addedPropertyName, addedPropertyValue) {
            var collectionManager = getContext().getCollection();
            collectionManager.createDocument(
                collectionManager.getSelfLink(),
                docToCreate,
                function(err, docCreated) {
                  if(err) throw new Error('Error:  ' + err.message);
                  docCreated[addedPropertyName] = addedPropertyValue;
                  getContext().getResponse().setBody(docCreated);
                });
        }
}

La stored procedure viene registrata eseguendo una richiesta POST nell'URI dbs/testdb/colls/testColl/sprocs con il corpo contenente la stored procedure da creare.The stored procedure is registered by executing a POST request against the URI dbs/testdb/colls/testColl/sprocs with the body containing the stored procedure to create. Trigger e funzioni definite dall'utente possono essere registrati in modo analogo eseguendo una richiesta POST rispettivamente su /triggers e /udfs.Triggers and UDFs can be registered similarly by issuing a POST against /triggers and /udfs respectively. Questa stored procedure può quindi essere eseguita tramite una richiesta POST sul relativo collegamento alle risorse:This stored procedure can then be executed by issuing a POST request against its resource link:

POST https://<url>/sprocs/<sproc> HTTP/1.1
authorization: <<auth>>
x-ms-date: Thu, 07 Aug 2014 03:43:20 GMT


[ { "name": "TestDocument", "book": "Autumn of the Patriarch"}, "Price", 200 ]

In questo caso, l'input nella stored procedure viene passato al corpo della richiesta.Here, the input to the stored procedure is passed in the request body. Notare che l'input viene passato come matrice JSON dei parametri di input.Note that the input is passed as a JSON array of input parameters. La stored procedure accetta il primo input come documento che rappresenta il corpo della risposta.The stored procedure takes the first input as a document that is a response body. Il formato della risposta ricevuta è il seguente:The response we receive is as follows:

HTTP/1.1 200 OK

{ 
  name: 'TestDocument',
  book: ‘Autumn of the Patriarch’,
  id: ‘V7tQANV3rAkDAAAAAAAAAA==‘,
  ts: 1407830727,
  self: ‘dbs/V7tQAA==/colls/V7tQANV3rAk=/docs/V7tQANV3rAkDAAAAAAAAAA==/’,
  etag: ‘6c006596-0000-0000-0000-53e9cac70000’,
  attachments: ‘attachments/’,
  Price: 200
}

A differenza delle stored procedure, non è possibile eseguire direttamente i trigger,Triggers, unlike stored procedures, cannot be executed directly. che vengono però eseguiti come parte di un'operazione o di un documento.Instead they are executed as part of an operation on a document. È possibile specificare i trigger da eseguire con una richiesta usando le intestazioni HTTP.We can specify the triggers to run with a request using HTTP headers. Di seguito è riportata una richiesta per creare un documento.The following is request to create a document.

POST https://<url>/docs/ HTTP/1.1
authorization: <<auth>>
x-ms-date: Thu, 07 Aug 2014 03:43:10 GMT
x-ms-documentdb-pre-trigger-include: validateDocumentContents 
x-ms-documentdb-post-trigger-include: bookCreationPostTrigger


{
   "name": "newDocument",
   “title”: “The Wizard of Oz”,
   “author”: “Frank Baum”,
   “pages”: 92
}

In questo caso, il pre-trigger da eseguire con la richiesta è specificato nell'intestazione x-ms-documentdb-pre-trigger-include.Here the pre-trigger to be run with the request is specified in the x-ms-documentdb-pre-trigger-include header. Di conseguenza, qualsiasi post-trigger viene indicato nell'intestazione x-ms-documentdb-post-trigger-include.Correspondingly, any post-triggers are given in the x-ms-documentdb-post-trigger-include header. Notare che è possibile specificare sia pre-trigger sia post-trigger per una determinata richiesta.Note that both pre- and post-triggers can be specified for a given request.

Codice di esempioSample code

Per trovare altri esempi di codice sul lato server, inclusi esempi relativi all'eliminazione in blocco e all'aggiornamento, vedere l'archivio GitHub.You can find more server-side code examples (including bulk-delete, and update) on our GitHub repository.

Si desidera condividere la stored procedure awesome?Want to share your awesome stored procedure? Inviare una richiesta di pull!Please, send us a pull-request!

Passaggi successiviNext steps

Quando sono presenti uno o più stored procedure, trigger e funzioni definite dall'utente create, è possibile caricarli e visualizzarli nel portale di Azure usando Esplora dati.Once you have one or more stored procedures, triggers, and user-defined functions created, you can load them and view them in the Azure portal using Data Explorer.

È inoltre possibile trovare i seguenti riferimenti e risorse utili per il percorso per altre informazioni sulla programmazione lato server Azure Cosmos DB:You may also find the following references and resources useful in your path to learn more about Azure Cosmos dB server-side programming: