Partager via


Bibliothèque de client Azure Cosmos DB pour JavaScript - version 4.0.0

/TypeScript

dernier badge npmÉtat de la build

Azure Cosmos DB est un service de base de données multimodèle globalement distribué qui prend en charge les bases de données de documents, de valeurs clés, à colonne large et de graphiques. Ce package est destiné aux applications JavaScript/TypeScript pour interagir avec les bases de données d’API SQL et les documents JSON qu’elles contiennent :

  • Créer des bases de données Cosmos DB et modifier leurs paramètres
  • Créer et modifier des conteneurs pour y stocker des collections de documents JSON
  • Créer, lire, mettre à jour et supprimer des éléments (documents JSON) dans vos conteneurs
  • Interroger les documents dans votre base de données avec une syntaxe de type SQL

Liens clés :

Prise en main

Prérequis

Abonnement Azure et compte API SQL Cosmos DB

Vous devez avoir un abonnement Azure et un compte Cosmos DB (API SQL) pour utiliser ce package.

Si vous n’avez pas encore de compte API SQL Cosmos DB, vous pouvez utiliser Azure Cloud Shell pour en créer un, en utilisant cette commande Azure CLI :

az cosmosdb create --resource-group <resource-group-name> --name <cosmos-database-account-name>

Vous pouvez aussi créer un compte dans le portail Azure.

NodeJS

Ce package est distribué via npm, qui est préinstallé avec NodeJS. Vous avez besoin de Node version 10 ou ultérieure.

CORS

Vous devez configurer des règles CORS (Cross-Origin Resource Sharing) pour votre compte Cosmos DB si votre développement est destiné à des navigateurs. Suivez les instructions fournies dans le document du lien pour créer des règles CORS pour votre compte Cosmos DB.

Installer ce package

npm install @azure/cosmos

Obtenir les informations d’identification du compte

Vous aurez besoin de fournir le point de terminaison du compte Cosmos DB et la clé associée. Pour obtenir ces informations, recherchez-les dans le portail Azure ou utilisez l’extrait de code Azure CLI ci-dessous. L’extrait de code est mis en forme pour l’interpréteur de commandes Bash.

az cosmosdb show --resource-group <your-resource-group> --name <your-account-name> --query documentEndpoint --output tsv
az cosmosdb keys list --resource-group <your-resource-group> --name <your-account-name> --query primaryMasterKey --output tsv

Créer une instance de CosmosClient

L’interaction avec Cosmos DB commence par une instance de la classe CosmosClient

const { CosmosClient } = require("@azure/cosmos");

const endpoint = "https://your-account.documents.azure.com";
const key = "<database account masterkey>";
const client = new CosmosClient({ endpoint, key });

async function main() {
  // The rest of the README samples are designed to be pasted into this function body
}

main().catch((error) => {
  console.error(error);
});

Par souci de simplicité, nous avons inclus les informations key et endpoint directement dans le code. Si vous souhaitez les charger à partir d’un fichier hors du contrôle de code source, utilisez un projet comme dotenv ou chargez-les des variables d’environnement

Dans les environnements de production, les secrets tels que les clés doivent être stockés dans Azure Key Vault

Concepts clés

Une fois que vous avez initialisé un CosmosClient, vous pouvez interagir avec les principaux types de ressources dans Cosmos DB :

  • Base de données : un compte Cosmos DB peut contenir plusieurs bases de données. Quand vous créez une base de données, vous spécifiez l’API que vous voulez utiliser pour l’interaction avec ses documents : SQL, MongoDB, Gremlin, Cassandra ou Azure Table. Utilisez l’objet Database pour gérer ses conteneurs.

  • Conteneur : un conteneur est une collection de documents JSON. Vous créez (insérez), lisez, mettez à jour et supprimez des éléments dans un conteneur en utilisant des méthodes sur l’objet Container.

  • Item: un élément est un document JSON stocké dans un conteneur. Chaque élément doit inclure une clé id dont la valeur identifie de manière unique l’élément dans le conteneur. Si vous ne fournissez pas de clé id, le SDK en génère une automatiquement.

Pour plus d’informations sur ces ressources, consultez Utilisation des bases de données, des conteneurs et des éléments Azure Cosmos.

Exemples

Les sections suivantes fournissent plusieurs extraits de code qui couvrent quelques-unes des tâches Cosmos DB les plus courantes, notamment :

Création d'une base de données

Après avoir authentifié votre CosmosClient, vous pouvez utiliser n’importe quelle ressource dans le compte. L’extrait de code ci-dessous crée une base de données d’API NOSQL.

const { database } = await client.databases.createIfNotExists({ id: "Test Database" });
console.log(database.id);

Créez un conteneur.

Cet exemple crée un conteneur avec les paramètres par défaut

const { container } = await database.containers.createIfNotExists({ id: "Test Database" });
console.log(container.id);

Utilisation de clés de partition

Cet exemple montre différents types de clés de partition prises en charge.

await container.item("id", "1").read();        // string type
await container.item("id", 2).read();          // number type
await container.item("id", true).read();       // boolean type
await container.item("id", {}).read();         // None type
await container.item("id", undefined).read();  // None type
await container.item("id", null).read();       // null type

Si la clé de partition se compose d’une valeur unique, elle peut être fournie sous forme de valeur littérale ou de tableau.

await container.item("id", "1").read();
await container.item("id", ["1"]).read();

Si la clé de partition se compose de plusieurs valeurs, elle doit être fournie sous forme de tableau.

await container.item("id", ["a", "b"]).read();
await container.item("id", ["a", 2]).read();
await container.item("id", [{}, {}]).read();
await container.item("id", ["a", {}]).read();
await container.item("id", [2, null]).read();

Insérer des éléments

Pour insérer des éléments dans un conteneur, transmettez un objet contenant vos données à Items.upsert. Le service Azure Cosmos DB nécessite que chaque élément ait une id clé. Si vous ne fournissez pas de clé id, le SDK en génère une automatiquement.

Cet exemple insère plusieurs éléments dans le conteneur

const cities = [
  { id: "1", name: "Olympia", state: "WA", isCapitol: true },
  { id: "2", name: "Redmond", state: "WA", isCapitol: false },
  { id: "3", name: "Chicago", state: "IL", isCapitol: false }
];
for (const city of cities) {
  await container.items.create(city);
}

Lire un élément

Pour lire un seul élément d’un conteneur, utilisez Item.read. Cette opération consomme moins de ressources que l’utilisation de SQL pour interroger par id.

await container.item("1", "1").read();

CRUD sur conteneur avec clé de partition hiérarchique

Créer un conteneur avec une clé de partition hiérarchique

const containerDefinition = {
  id: "Test Database",
  partitionKey: {
    paths: ["/name", "/address/zip"],
    version: PartitionKeyDefinitionVersion.V2,
    kind: PartitionKeyKind.MultiHash,
  },
}
const { container } = await database.containers.createIfNotExists(containerDefinition);
console.log(container.id);

Insérer un élément avec une clé de partition hiérarchique définie comme - ["/name", "/address/zip"]

const item = {
  id: 1,
  name: 'foo',
  address: {
    zip: 100
  },
  active: true
}
await container.items.create(item);

Pour lire un seul élément à partir d’un conteneur avec une clé de partition hiérarchique définie comme : ["/name", "/address/zip"],

await container.item("1", ["foo", 100]).read();

Interroger un élément avec une clé de partition hiérarchique avec la clé de partition hiérarchique définie comme - ["/name", "/address/zip"],

const { resources } = await container.items
  .query("SELECT * from c WHERE c.active = true", {
          partitionKey: ["foo", 100],
        })
  .fetchAll();
for (const item of resources) {
  console.log(`${item.name}, ${item.address.zip} `);
}

Supprimer un élément

Pour supprimer des éléments d’un conteneur, utilisez Item.delete.

// Delete the first item returned by the query above
await container.item("1").delete();

Interroger la base de données

Une base de données API SQL Cosmos DB prend en charge l’interrogation des éléments dans un conteneur avec une requête Items.query utilisant une syntaxe de type SQL :

const { resources } = await container.items
  .query("SELECT * from c WHERE c.isCapitol = true")
  .fetchAll();
for (const city of resources) {
  console.log(`${city.name}, ${city.state} is a capitol `);
}

Effectuez des requêtes paramétrables en transmettant un objet contenant les paramètres et leurs valeurs à Items.query :

const { resources } = await container.items
  .query({
    query: "SELECT * from c WHERE c.isCapitol = @isCapitol",
    parameters: [{ name: "@isCapitol", value: true }]
  })
  .fetchAll();
for (const city of resources) {
  console.log(`${city.name}, ${city.state} is a capitol `);
}

Pour plus d’informations sur l’interrogation des bases de données Cosmos DB avec l’API SQL, consultez Interroger des données Azure Cosmos DB avec des requêtes SQL.

Modifier le modèle d’extraction de flux

Le flux de modification peut être extrait pour une clé de partition, une plage de flux ou un conteneur entier.

Pour traiter le flux de modification, créez un instance de ChangeFeedPullModelIterator. Lorsque vous créez ChangeFeedPullModelIteratorinitialement , vous devez spécifier une valeur obligatoire changeFeedStartFrom à l’intérieur ChangeFeedIteratorOptions du qui se compose à la fois de la position de départ pour la lecture des modifications et de la ressource (une clé de partition ou un FeedRange) pour laquelle les modifications doivent être extraites. Vous pouvez éventuellement utiliser maxItemCount dans ChangeFeedIteratorOptions pour définir le nombre maximal d’éléments reçus par page.

Remarque : Si aucune valeur n’est changeFeedStartFrom spécifiée, le flux de modification est extrait pour un conteneur entier à partir de Now().

Il existe quatre positions de départ pour le flux de modification :

  • Beginning
// Signals the iterator to read changefeed from the beginning of time.
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Beginning();
}
const iterator = container.getChangeFeedIterator(options);
  • Time
// Signals the iterator to read changefeed from a particular point of time.
const time = new Date("2023/09/11") // some sample date
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Time(time);
}
  • Now
// Signals the iterator to read changefeed from this moment onward.
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Now();
}
  • Continuation
// Signals the iterator to read changefeed from a saved point.
const continuationToken = "some continuation token recieved from previous request";
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Continuation(continuationToken);
}

Voici un exemple d’extraction du flux de modification pour une clé de partition

const partitionKey = "some-partition-Key-value";
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Beginning(partitionKey),
};

const iterator = container.items.getChangeFeedIterator(options);

while (iterator.hasMoreResults) {
  const response = await iterator.readNext();
  // process this response
}

Comme le flux de modification constitue effectivement une liste d’éléments infinie qui englobe toutes les écritures et mises à jour ultérieures, la valeur de hasMoreResults est toujours true. Lorsque vous essayez de lire le flux de modification et qu’aucune nouvelle modification n’est disponible, vous recevez une réponse avec l’état NotModified.

Des instructions d’utilisation plus détaillées et des exemples de flux de modification sont disponibles ici.

Gestion des erreurs

Le Kit de développement logiciel (SDK) génère différents types d’erreurs qui peuvent se produire pendant une opération.

  1. ErrorResponse est levée si la réponse d’une opération retourne un code d’erreur de >=400.
  2. TimeoutError est levée si Abort est appelé en interne en raison du délai d’expiration.
  3. AbortError est levée si un utilisateur a passé le signal à l’origine de l’abandon.
  4. RestError est levée en cas d’échec de l’appel système sous-jacent en raison de problèmes réseau.
  5. Erreurs générées par les devDependencies. Par exemple @azure/identity le package peut lever CredentialUnavailableError.

Voici un exemple de gestion des erreurs de type ErrorResponse, TimeoutError, AbortErroret RestError.

try {
  // some code
} catch (err) {
  if (err instanceof ErrorResponse) {
    // some specific error handling.
  } else if (err instanceof RestError) {
    // some specific error handling.
  }
  // handle other type of errors in similar way.
  else {
    // for any other error.
  }
}

Il est important de gérer correctement ces erreurs pour vous assurer que votre application peut récupérer correctement en cas de défaillance et continuer à fonctionner comme prévu. Vous trouverez plus d’informations sur certaines de ces erreurs et leurs solutions possibles ici.

Dépannage

Général

Quand vous interagissez avec Cosmos DB, les erreurs retournées par le service correspondent aux codes d’état HTTP retournés pour les requêtes d’API REST :

Codes d’état HTTP pour Azure Cosmos DB

Conflits

Par exemple, si vous essayez de créer un élément avec un id qui est déjà utilisé dans votre base de données Cosmos DB, une erreur 409 est retournée, indiquant le conflit. Dans l’extrait suivant, l’erreur est prise en charge correctement via l’interception de l’exception et l’affichage d’informations supplémentaires sur l’erreur en question.

try {
  await containers.items.create({ id: "existing-item-id" });
} catch (error) {
  if (error.code === 409) {
    console.log("There was a conflict with an existing item");
  }
}

Transpilation

Les SDK Azure sont conçus pour prendre en charge la syntaxe JavaScript ES5 et les versions LTS de Node.js. Si vous avez besoin d’une prise en charge de runtimes JavaScript antérieurs tels qu’Internet Explorer ou Node 6, vous devez transpiler le code des SDK dans le cadre de votre processus de build.

Gérer les erreurs temporaires avec de nouvelles tentatives

Quand vous utilisez Cosmos DB, vous pouvez rencontrer des défaillances temporaires causées par des limites du taux de transfert appliquées par le service ou d’autres problèmes passagers comme des pannes du réseau. Pour plus d’informations sur la gestion de ces types d’échecs, consultez le modèle Nouvelle tentative dans le guide des modèles de conception de cloud et le modèle Disjoncteur connexe.

Journalisation

L’activation de la journalisation peut vous aider à mieux comprendre les échecs. Pour avoir un journal des requêtes et réponses HTTP, définissez la variable d’environnement AZURE_LOG_LEVEL sur info. Vous pouvez également activer la journalisation au moment de l’exécution en appelant setLogLevel dans le @azure/logger. Lors de l’utilisation AZURE_LOG_LEVEL , veillez à la définir avant l’initialisation de la bibliothèque de journalisation. Dans l’idéal, transmettez-le via la ligne de commande, si vous utilisez des bibliothèques comme dotenv , assurez-vous que ces bibliothèques sont initialisées avant de journaliser la bibliothèque.

const { setLogLevel } = require("@azure/logger");
setLogLevel("info");

Pour obtenir des instructions plus détaillées sur l’activation des journaux, consultez les documents relatifs au package @azure/logger.

Diagnostics

La fonctionnalité Diagnostics Cosmos fournit des insights améliorés sur toutes les opérations de vos clients. Un objet CosmosDiagnostics est ajouté à la réponse de toutes les opérations du client. Par exemple :

  • Opération de recherche de point reponse - item.read(), container.create(), database.delete()
  • Opération de requête reponse -queryIterator.fetchAll(),
  • Opérations en bloc et Batch -item.batch().
  • Objets de réponse d’erreur/d’exception.

Un objet CosmosDiagnostics est ajouté à la réponse de toutes les opérations du client. Il existe 3 niveaux de diagnostic Cosmos, info, débogage et débogage-unsafe. Lorsque seules les informations sont destinées aux systèmes de production, le débogage et le débogage sont destinés à être utilisés pendant le développement et le débogage, car ils consomment des ressources beaucoup plus élevées. Le niveau de diagnostic Cosmos peut être défini de deux façons

  • Par programme
  const client = new CosmosClient({ endpoint, key, diagnosticLevel: CosmosDbDiagnosticLevel.debug });
  • Utilisation de variables d’environnement. (Le niveau de diagnostic défini par la variable d’environnement a une priorité plus élevée que sa définition via les options client.)
  export AZURE_COSMOSDB_DIAGNOSTICS_LEVEL="debug"

Cosmos Diagnostic a trois membres

  • Type ClientSideRequestStatistics : contient les détails de diagnostic des agrégats, notamment les recherches de métadonnées, les nouvelles tentatives, les points de terminaison contactés et les statistiques de demandes et de réponses telles que la taille et la durée de la charge utile. (est toujours collecté, peut être utilisé dans les systèmes de production.)

  • DiagnosticNode : structure de type arborescence qui capture des informations de diagnostic détaillées. Similaire à l’enregistrement har présent dans les navigateurs. Cette fonctionnalité est désactivée par défaut et est destinée au débogage d’environnements hors production uniquement. (collectés au niveau du diagnostic déboguer et déboguer-unsafe)

  • ClientConfig : capture les informations essentielles relatives aux paramètres de configuration du client lors de l’initialisation du client. (collectés au niveau du diagnostic déboguer et déboguer-unsafe)

Veillez à ne jamais définir le niveau debug-unsafe de diagnostic sur dans l’environnement de production, car ce niveau CosmosDiagnostics capture les charges utiles de requête et de réponse et si vous choisissez de les journaliser (il est journalisé par défaut par @azure/logger au verbose niveau). Ces charges utiles peuvent être capturées dans vos récepteurs de journaux.

Consommation des diagnostics

  • Depuis diagnostics est ajouté à tous les objets Response. Vous pouvez y accéder CosmosDiagnostic par programmation comme suit.
  // For point look up operations
  const { container, diagnostics: containerCreateDiagnostic } =
    await database.containers.createIfNotExists({
      id: containerId,
      partitionKey: {
        paths: ["/key1"],
      },
  });

  // For Batch operations
   const operations: OperationInput[] = [
    {
      operationType: BulkOperationType.Create,
      resourceBody: { id: 'A', key: "A", school: "high" },
    },
  ];
  const response = await container.items.batch(operations, "A"); 
  
  // For query operations
  const queryIterator = container.items.query("select * from c");
  const { resources, diagnostics } = await queryIterator.fetchAll();

  // While error handling
  try {
    // Some operation that might fail
  } catch (err) {
    const diagnostics = err.diagnostics
  }
  • Vous pouvez également journaliser diagnostics à l’aide de @azure/logger, le diagnostic est toujours journalisé à l’aide verbose du @azure/logger niveau . Par conséquent, si vous définissez Niveau de diagnostic sur debug ou et debug-unsafe@azure/logger niveau sur verbose, diagnostics sera journalisé.

Étapes suivantes

Autres exemples de code

Plusieurs exemples sont disponibles dans le dépôt GitHub du SDK. Vous y trouverez des exemples de code pour d’autres scénarios fréquents associés à l’utilisation du service Cosmos DB :

  • Opérations de base de données
  • Opérations sur le conteneur
  • Opérations d'élément
  • Configuration de l’indexation
  • Lecture d’un flux de modification de conteneur
  • Procédures stockées
  • Modification des paramètres de débit de base de données/conteneur
  • Opérations d’écriture multirégion

Limites

Actuellement, les fonctionnalités ci-dessous ne sont pas prises en charge. Pour les options alternatives, case activée la section Solutions de contournement ci-dessous.

Limitations du plan de données :

  • Requêtes avec COUNT à partir d’une sous-requête DISTINCT
  • Accès direct en mode TCP
  • Les requêtes agrégées entre partitions, telles que le tri, le comptage et les requêtes distinctes, ne prennent pas en charge les jetons de continuation. Requêtes streamables, telles que SELECT * FROM WHERE , prend en charge les jetons de continuation. Consultez la section « Solution de contournement » pour exécuter des requêtes non streamables sans jeton de continuation.
  • Flux de modification : Processeur
  • Flux de modification : lire les valeurs de clé de plusieurs partitions
  • Modifier le modèle d’extraction de flux toutes les versions et le mode suppression #27058
  • Prise en charge du modèle d’extraction de flux de modification pour les clés de partition hiérarchiques partielles #27059
  • ORDER BY entre partitions pour les types mixtes
  • Limitations du plan de contrôle :

    • Obtenir les métriques CollectionSizeUsage, DatabaseUsage et DocumentUsage
    • Créer un index géospatial
    • Mettre à jour le débit de mise à l’échelle automatique

    Solutions de contournement

    Jeton de continuation pour les requêtes de partitions croisées

    Vous pouvez obtenir des requêtes entre partitions avec prise en charge du jeton de continuation à l’aide du modèle Side car. Ce modèle permet également aux applications d’être constituées de technologies et de composants hétérogènes.

    Exécution d’une requête sur plusieurs partitions non stremables

    Pour exécuter des requêtes non streamables sans utiliser de jetons de continuation, vous pouvez créer un itérateur de requête avec la spécification et les options de requête requises. L’exemple de code suivant montre comment utiliser un itérateur de requête pour extraire tous les résultats sans avoir besoin d’un jeton de continuation :

    const querySpec = {
      query: "SELECT * FROM c WHERE c.status = @status",
      parameters: [{ name: "@status", value: "active" }],
    };
    const queryOptions = {
      maxItemCount: 10, // maximum number of items to return per page
      enableCrossPartitionQuery: true,
    };
    const querIterator = await container.items.query(querySpec, queryOptions);
    while (querIterator.hasMoreResults()) {
      const { resources: result } = await querIterator.fetchNext();
      //Do something with result
    }
    

    Cette approche peut également être utilisée pour les requêtes pouvant être diffusées en continu.

    Opérations du plan de contrôle

    En règle générale, vous pouvez utiliser le portail Azure, l’API REST du fournisseur de ressources Azure Cosmos DB, Azure CLI ou PowerShell pour les limitations non prises en charge du plan de contrôle.

    Documentation complémentaire

    Pour une documentation plus complète sur le service Cosmos DB, consultez la documentation du service Cosmos DB sur docs.microsoft.com.

    Contribution

    Si vous souhaitez contribuer à cette bibliothèque, lisez le guide de contribution pour en savoir plus sur la génération et le test du code.

    Impressions