Juli 2016

Band 31, Nummer 7

Dieser Artikel wurde maschinell übersetzt.

Datenpunkte – Das neue Node.js SDK für Azure DocumentDB

Durch Julie Lerman

Julie LermanIm vergangenen Jahr habe ich eine Beispiel-app entwickeln, die auf dem Front-End eine serverseitige API in Node.js und Azure DocumentDB für den Datenspeicher geschrieben Aurelia verwendet. Neben der Verwendung von Node.js für die serverseitige API, nutzt meiner app auch das Node.js-SDK für Azure DocumentDB. Stattdessen als die vollständige app beschrieben, ich werde zeigen Sie auf die älteren Artikel vom November (msdn.com/magazine/mt620011) und Dezember 2015 (msdn.com/magazine/mt595750) Wenn schrieb ich über diese Anwendung. Auch können Sie die ursprüngliche Anwendung herunterladen und vergleichen Sie sie mit der neuen Quelle, die in diesem Artikel beschriebenen entsprechend aktualisiert. Und da ich die app häufig und Anpassung bin Sie können immer betrachten Sie das GitHub-Repository auf bit.ly/25crZAG.

Aufgrund von Änderungen Aurelia, zu viele Node.js-Pakete, die ich verwende, DocumentDB-Funktionen und sogar auf die oben genannten SDK in den vergangenen Monaten, war es Zeit für eine Reihe von Updates und nicht nur für Pakete jedoch auch aktualisieren, meinen Code um neuere Funktionen in der gesamten nutzen. Ich wird nicht auf Aurelia hier beheben; Stattdessen werde ich konzentriere ich mich auf Änderungen in DocumentDB und zum Ändern von Mein Codes Node.js-API diese Änderungen profitieren aufbewahren.

Schritt 1: Implementieren von Zusagen für asynchrone Aufrufe

Ich habe zunächst wurde "Npm Update" auf meinem Node.js-Projekt ausgeführt werden. Das Update ist auch ein Fehler aufgetreten, aber später Ausführen der app weniger erfolgreich war. Kann ich Fehler schnell einen, die erzählte mir, dass eigene Verwendung von Rückrufen zu einem Problem, hatte. Irgendwo bevorzugt eine API in die Tiefen der Abhängigkeiten, nun den JavaScript-Zusagen über Rückrufe. Das Paradigma des Zusagen (etwa Async/await in .NET) schon seit einer Weile, aber ich hatte den vertraut Pfad der Verwendung von Rückrufen beim Erstellen des Beispiels ausgeführt. Jetzt war es Zeit beschäftigen, meine Digit, meine Atem halten, und ersetzen alle Rückrufe in der Node.js-API verstopft. Leider war nicht nur darum, ersetzen die Begriffe, aber es erforderlich, die tatsächliche Struktur des Codes ändern. In den Schichten meiner API war ich Rückrufe in der Datei DocDBUtils verwenden, die direkt an die Node.js-SDK für DocumentDB gesprochen. Und habe ich in der DocDBDao-Klasse, die den Dienstprogrammen (in DocDBUtils) und das SDK gesprochen Rückrufe verwendet. Dies bedeutete, dass bei der Kommunikation mit den Dienstprogrammen eine geschichteten System von Rückrufen musste. Abschließend versucht die ninja.js-Klasse Aufrufe in die DocDBDao-Klasse, Datenabruf Trigger oder Updates. Diese Methoden auch Rückrufe verwendet und die Rückrufe der niedrigeren Dateien abhängen. Daher musste ich Sie Versprechen von unten (DocDBUtils) implementieren.

Es gibt eine Reihe von JavaScript-APIs, mit denen die Implementierung von Zusagen. Eine wird aufgerufen, Q und das DocumentDB-Team erstellt einen Wrapper für die Node.js-SDK, das f verwendet und daher vereinfacht die Verwendung von Zusagen mit DocumentDB eine viel einfachere Aufgabe codieren. Dieser Wrapper, Documentdb-Q-Zusagen, ist auf GitHub unter bit.ly/1pWYHCE.

Aus diesem Grund wurde mein erste Schritt F mit den Node Package Manager (Npm) zu installieren:

npm install documentdb-q-promises

In allen Knoten Klassen, die das Basis-SDK (die oben erwähnten Klassen sowie eine aufgerufene api.js) verwendeten musste ich dann die Anweisungen "erforderlich" zu ändern, die ursprünglich mein wissen, dass die DocumentClient-Klasse aus dem ersten SDK verwendet Klassen ermöglicht wurden:

var DocumentDBClient = require('documentdb').DocumentClient;

Zeigen Sie auf die DocumentClientWrapper-Klasse aus der neuen API:

var DocumentDBClient = require('documentdb-q-promises').DocumentClientWrapper;

Die DocDbUtils-Klasse ist ein zusätzlicher Verweis der F-Bibliothek direkt ein, damit der DocumentDBClient als definiert ist:

var DocumentClient = require('documentdb-q-promises').DocumentClientWrapper
  , Q = require("q");

Als Nächstes musste ich den Rückrufcode, um das Versprechen Umgestalten. Kann ich Zeitlang mit diesem eine bis das Muster nach unten musste. Bei einigen Funktionen arbeiten in der DocDBUtils-Klasse war ich dann, können Sie leichter von den Funktionen in den Klassen zu beheben, die diese Klasse aufrufen. Doch bevor ich zu diesem Punkt gelangt ist, war definitiv eine anstrengende Prozess: Ändern Sie Code, Debuggen, lesen Sie die Fehler, etwas mehr scratch-Kopf, Google und ändern Sie den Code erneut. Gab es ein wenig griping auf Twitter, sodass meine Freunde mich aus meinem Kopf zu stark beeinträchtigt. Das war nicht so viel, da es sehr schwierig ist, aber nur weil – unabhängig von meinem Programmierung – bin ich immer noch etwas ein Noob in JavaScript.

Beispielsweise am Anfang der ersten Funktion erreicht wird, wenn die API ausgeführt wird: der Init-Methode DocDbDao.js. Diese Methode stellt sicher, dass der Rest API das DocumentDB-Konto kennt, verbindet mithilfe der Authentifizierungsschlüssel und den Namen der Datenbank kennt, siehe Abbildung 1.

Abbildung 1 die ursprüngliche GetOrCreateDatabase Methode mithilfe von Rückrufen

getOrCreateDatabase: function (client, databaseId, callback) {
  var querySpec = { *query for database name defined here* };
  client.queryDatabases(querySpec).toArray(function (err, results) {
    if (err) {
        callback(err);
    } else {
      if (results.length === 0) {
          var databaseSpec = {
            id: databaseId
          };
          client.createDatabase(databaseSpec, function (err, created) {
            callback(null, created);
          });
      } else {
        callback(null, results[0]);
      }
    }
  });
},

GetOrCreateDatabase wird aus der Init-Funktion in der DocDbDao-Klasse aufgerufen. Der Parameter mit dem Namen Client ist eine Instanz des DocumentDBClient aus dem ursprünglichen SDK.  Der dritte Parameter, mit dem Namen Rückruf, der an die aufrufende Funktion verweist, in diesem Fall Init. Die GetOrCreateDatabase-Methode definiert eine Abfrage in der Variablen QuerySpec und ruft dann client.queryDatabase mit der Abfrage. Wenn QueryDatabase einen Fehler zurückgibt, wird GetOrCreateDatabase, Fehler beim Sichern der aufrufenden Funktion über den Rückruf übergeben. Andernfalls überprüft er die Ergebnisse. Wenn results.length 0 ist, wird eine neue Datenbank erstellt und übergibt dann CreateDatabase zurück an die aufrufende Funktion zurückgegebenen Informationen. Wenn results.length nicht 0 ist, wird das erste Element im Array der Rückruf zurückgegeben.

Nun werfen wir einen Blick auf diese dieselbe Funktion, in Abbildung 2, überarbeitet, um den Einsatz von Zusagen (Denken Sie daran, diese wie in Microsoft .NET Framework Async/await), durch die Nutzung der Implementierung von Zusagen, Q.

Abbildung 2 GetOrCreateDatabase mithilfe von Zusagen

getOrCreateDatabase: function (client, databaseId) {
  var querySpec = { *query for database name defined here* };
    return client.queryDatabases(querySpec).toArrayAsync().then(function (results) {
      if (results.length === 0) {
          var databaseSpec = {
              id: databaseId
        };
        client.createDatabaseAsync(databaseSpec)
          .then(function (databaseResponse) {
            db = databaseResponse.resource;
            return client.createCollectionAsync(db._self, collectionDefinition);
          })
      }
      return results.feed[0];
  },
      function (err) { return err; }
  );
}

Als Erstes zu beachten ist, kein Rückruf in die Parameterliste für die Funktion vorhanden ist. Nach dem Definieren der Abfrage, die Funktion übernimmt den Aufruf von QueryDatabases, aber nicht wie zuvor. Dieses Mal verwende ich den QueryDatabases-Wrapper, die durch das neue SDK definiert. Anstatt ToArray für QueryDatabases aufrufen, verwendet die ToArrayAsync Methode, die eine Reihe von asynchronen Methoden, die vom Documentdb-Q-Zusagen SDK bereitgestellt werden. ToArrayAsync gibt eine Instanz eines Promise-Typs definiert, die von der F-Bibliothek zurück. Promise verfügt über die "then" (vergleichbar mit der "await", die Sie möglicherweise aus .NET Framework kennen) Methode, mit der Sie eine Funktion zum Ausführen von bei Beendigung des Aufrufs queryDatabases.toArrayAsync zu definieren. Das erste Bit der Logik gibt an, was tun, wenn der Aufruf erfolgreich ist. Wie zuvor suchen um festzustellen, ob die Länge 0 ist, gibt an, dass vorhanden nicht die Datenbank noch. Ist dies der Fall, dann kann ich eine neue Datenbank erstellen, aber dieses Mal jedoch mithilfe der CreateDatabaseAsync-Methode, die wie der anderen Async-Methode gibt ein zusageobjekt zurück. Wenn die Datenbank erfolgreich erstellt wurde, verarbeiten ich dann die Antwort der Datenbank. Ich habe einige zusätzliche Logik, um die Erstellung der Datenbank ausgelassen, aber Sie sehen, wenn Sie den Code herunterladen.

Der nächste Teil der Methode gibt an, was geschehen soll, wenn die Abfrage eine Datenbank einfach findet in der das erste Element in den Ergebnissen zurückgeben. Die Ergebnisse der ToArrayAsync enthalten eine feed-Eigenschaft, die die Ergebnisse umschließt die warum die Syntax als results.feed[0].

Abschließend die QueryDatabases beim Aufruf fehlschlägt die Funktion ein Fehler zurückgegeben.

Nun, da Sie dadurch vertraut gemacht haben, sehen wir uns das Muster erneut:

CallToAsyncFuction().then(function to execute when complete){
                          success logic
                          },
                          function(err) {failure logic}
                          );

Sie rufen Sie eine der asynchronen Methoden und verwenden die then-Methode zum Definieren einer Laufzeitvariablen Funktion ausführen, wenn der Aufruf abgeschlossen ist. Ändern Sie in der Funktion geben Sie zunächst Code ausgeführt werden, wenn die Methode erfolgreich war (optional ein Ergebnis zurückgeben), und klicken Sie dann code ausführen, schlägt die Methode (auch die Möglichkeit, ein Ergebnis zurückgibt).

Ich habe dieses Muster in die überarbeitete-API, ersetzen alle Konstrukte Rückruf in die drei Modelle implementiert.

Ich kann jedoch einfach jetzt Debuggen und erwarten, dass dies funktioniert, weil ich einen Wasserfall von Zusagen habe, beginnend mit der Ninjas-Klasse, die noch das neue Documentdb-Q-Zusagen SDK nicht bekannt ist. Sie können versuchen, die anderen Rückrufe in das ursprüngliche Beispiel zu ersetzen oder die vollständig aktualisierte Lösung im Download.

Nun meine Node.js Interaktion mit DocumentDB verwendet empfohlene Technologie, daher betrachten einige weitere Funktionen in DocumentDB und erläutere ich, wie ich sie in der-API implementiert.

Parametrisierte Abfragen

In der ersten Iteration der mein Beispiel, ich habe etwas in die ninja.js-Klasse, die ich in meiner apps .NET nie tun würden – ich gehackt Abfragezeichenfolgen zusammen mit der Verkettung von Zeichenfolgen. Mindestens habe ich die ES6-fähigen zeichenfolgeninterpolation Verkettung dazu verwendet, aber dennoch ich schäme mich ein wenig, und es wird keine Entschuldigung. Außer vielleicht zwei. Die erste ist, war ich aus den bereitgestellten Beispielen lernen und noch nicht den Kopf zerbrochen, verwenden. (Wird auch dazu?) Darüber hinaus wird die Sicherheit nicht größter im Moment war, da eine SQL-Angriff auf ein Azure-DocumentDB nicht so großes Problem aufgrund der Weise Abfragen in der Datenbank arbeiten. Auch die Dokumentation sagt, dass DocumentDB nicht wirklich am häufigsten verwendeten Typen von Injection-Angriffe anfällig ist, obwohl besteht immer die Möglichkeit von einer Evildoer suchen Injection nutzen können. Weiterhin, es ist immer ratsam, die Sicherheit sehr vorsichtig sein, und parametrisierte Abfragen wurden eine empfohlene Methode für den Datenzugriff über einen langen Zeitraum.

In der früheren Version des Beispiels definiert eine Filterfunktion Typ QuerySpec mit einer Eigenschaft, die benannte Abfrage. Der Eigenschaftswert für die Abfrage wurde SQL verwendet, um eine Reihe von Ninjas aus DocumentDB abgerufen:

var querySpec = {
  query:
  'SELECT ninja.id, ninja.Name,ninja.ServedInOniwaban,ninja.DateOfBirth
  FROM ninja'
}

Die Filter-Funktion liest einen Filterwert in der URL enthalten. Wenn der Benutzer für jede Ninja durchsucht, deren Name "San" enthält, wird die URL beispielsweise Localhost:9000/api/Ninjas? Q = San. Die ursprüngliche Funktion erstellt ein Prädikat durch den, im Filterwert request.query.q, mit dem Prädikat für einfach verketten:

q = ' WHERE CONTAINS(ninja.Name,"' + request.query.q + '")';

Ich angehängt dann das Prädikat der grundlegenden Abfrage, die in querySpec.query gespeichert wurde.

Obwohl Injection-Angriffe nicht annähernd so einfach mit einem Filterwert, habe ich den Teil der Logik mit einem Parameter ersetzt, die DocumentDB verstehen, wird. Anstatt den Filterwert eingegeben haben, durch den Endbenutzer (San) zu verketten, verwende ich Parameterplatzhalter @namepart im Prädikat aufgerufen. Dann füge ich eine neue Eigenschaft zu QuerySpec als Parameter bezeichnet werden und, mit JSON-Formatierung, definieren mit Name-Wert-Eigenschaften, die DocumentDB gesucht wird. Dann kann ich den Namen des Parameters und der Wert für das Übergeben von der URL angeben:

querySpec.query += " WHERE CONTAINS(ninja.Name, @namepart)";
  querySpec.parameters = [{
    name: '@namepart',
    value: request.query.q
}]

DocumentDB wird führen Sie dies als eine parametrisierte Abfrage also alle schädliche SQL Meine Daten beeinträchtigen kann.

OK, das ist also ein wenig hart, aber es ist, wie viele von uns zu muss SelfLinks gegen jede Art von Objekt erschien, ob es sich um eine Datenbank, eine Auflistung, ein Dokument oder ein anderes Objekt in DocumentDB war. Der SelfLink-Wert ist, wie das Objekt selbst in DocumentDB identifiziert. Müssen Sie DocumentDB mit einem bekannten Bezeichner Abfragen – Datenbank oder der Auflistung oder den Identitätswert eines Dokuments – um die SelfLink zu erhalten, damit Sie andere Vorgänge ausführen können. SelfLinks sind immer noch vorhanden, aber Sie interagieren mit einem Objekt nicht mehr benötigen. Wenn Sie wissen, dass die Details, um eine Verknüpfung zu einem Objekt zu erstellen, können Sie, die anstelle der SelfLink verwenden. Ich zeige Ihnen nun, dass in Kürze in Kombination mit der nächsten Funktion ich in meinem Beispiel überarbeitete genutzt haben: Upserts.

Ersetzen Ersetzen durch Upsert

War ich gerne die umständliche Aktualisierungsfunktion in Meine API entfernen erforderlich, dass ich zuerst das Element aktualisiert werden, aus der Datenbank abzurufen:

  1. Stellen Sie sicher, dass sie vorhanden war
  2. Erhalten Sie Zugriff auf die selfLink
  3. Zugriff auf das vollständige Dokument hat für den Fall, dass das Element in der Update-Methode übergeben eine begrenzte schema

Klicken Sie dann musste aktualisiert Felder aus dem Dokument mit den Werten aus dem Element, das an die Updatemethode übergeben werden, von der Clientanwendung aus der Datenbank abgerufen werden. Schließlich musste ich DocumentDB das bestehende Dokument in der Datenbank mit diesem geänderten Dokument ersetzen zu informieren. Sie können dem früheren Artikel oder Beispiel sehen Sie sich die UpdateItem-Funktion in DocDbDao Wenn Sie neugierig davon sind alle sah besuchen.

Im Oktober kündigte Microsoft Glücklicherweise das Hinzufügen von atomaren Upsert-Funktionen, documentdb, wodurch es zu ermitteln, ob ein bestimmtes Dokument eingefügt oder aktualisiert werden muss. Finden Sie unter dem zugehörigen Blogbeitrag unter bit.ly/1G5wtpY für eine ausführlichere Erklärung.

Upsert können Sie eine einfache Aktualisierung mithilfe des Dokuments zur hand haben. Das Documentdb-Q-Zusagen-SDK stellt eine asynchrone Version ersetzen. Hier ist meine überarbeitete Update-Funktion:

updateItem: function (item) {
  var self = this;
  var docLink = "dbs/Ninjas/colls/Ninjas";
  item.DateModified = Date.now();
  return self.client.upsertDocumentAsync(docLink, item).then(function (replaced) {
    return replaced;
  },
    function (err) {
    return err;
    }
  );
},

Beachten Sie, dass der DocLink-Wert, den ich erstellen werde. Dies ist die neue Funktion, die ich erwähnt habe, das hilft mir, Vorsichtsmaßnahmen, die tatsächlichen SelfLink aus der Datenbank für das Dokument, das aktualisiert werden soll. Ich lege einfach fest, dass die Datenbank Ninjas heißt und die Auflistung auch mit Ninjas benannt werden. Ich übergeben den DocLink-Wert zusammen mit dem Element, das vom Client an den Befehl UpsertDocumentAsync kam sowie anschließend wieder der boolesche Wert (ersetzt), die zurückgegeben wird, wenn der Befehl ausgeführt wurde. Beachten Sie auch zusammen mit dem Async-Befehl, ich habe diese Logik, um das Versprechen, die von der asynchronen Methode zurückgegebene nutzen geändert werden. Sie können feststellen, da ich dann auf die asynchrone Methode Einfüge.

DocumentDB noch viel mehr hinzugefügt wurde

Während meiner kleinen Beispiel nur einige der neuen Funktionen nutzt, noch viel mehr hinzugefügt wurde DocumentDB da habe ich meinen früheren Artikeln. Weitere SQL-Befehle sind vorhanden, einschließlich oben für das Paging und ORDER BY für die Sortierung. ORDER BY hängt von Indizes für Auflistungen, das macht Sinn, da es hier große Datenmengen handelt, und Sie müssen die Datenbank an, um Ihre Bedürfnisse erfüllen. Es ist auch möglich, die Indexierungsrichtlinien in vorhandenen Sammlungen anstatt mit einer vorherigen unglücklicher live zu ändern. Wenn Sie die Client-API für .NET für DocumentDB verwenden, der LINQ-Anbieter hat stehen viel umfangreicher, erhalten Sie Informationen zu auf bit.ly/1Od3ia2.

DocumentDB ist für das Speichern von großen Datenmengen und arbeitet Microsoft Access effizienter und kostengünstiger gestalten. Zu diesem Zweck eingeführt, das Unternehmen Partitionsschlüssel, ein zentrales Feature von DocumentDB, mit der Sie Partition Sammlungen noch mindestens ein "große Datenmengen auf hohe Raten oder Anwendungen, die hohen Durchsatz, geringe Latenz Zugriff auf Daten erforderlich ist." Erfahren Sie mehr über Partitionsschlüssel an bit.ly/1TpOxFj.

Microsoft behandelt auch Tarif Probleme, die Benutzer zusätzliche Auflistungen erstellen, da Gebühren, die die Anzahl der Sammlungen zugewiesen wurden beibehalten. Neue Pläne basieren auf dem Volume und Durchsatz erzielt wird, können Sie weitere Auflistungen verwenden und brauchen sich nicht ganz so viel über übermäßig hohen Kosten für Auflistungen, die viele Aktivitäten verfügen. Jede Auflistung aber weiterhin enthält einen minimalen Durchsatz. Das Team weiterhin aussehen zu Ressourcenverwendung zu verbessern, damit sie in Zukunft dieser Mindestwerte senken können. Weitere Informationen zu den neuen Tarif Plänen, finden Sie auf bit.ly/1jgnbn9.

DocumentDB-Tools wurden ebenfalls geändert, und sie werden weiterhin in Zukunft tun. Es gibt weitere Möglichkeiten, Ihre DocumentDB im Azure-Verwaltungsportal zu untersuchen und die Migrationstools wurden weitere Funktionen abgerufen. Ich besonders gerne finden Sie unter wurde eine Änderung war, dass die Cloud Explorer-Erweiterung für Visual Studio jetzt unterstützt eine Verbindung mit und Durchsuchen von DocumentDB Daten. Sie können auch bearbeiten und speichern Sie Änderungen an den Rohdaten über die Cloud Explorer, aber zu diesem Zeitpunkt Abfragen nicht möglich ist.

Um mit der wachsenden Featuresatz halten möchten, achten Sie auf die DocumentDB-getaggte Blogbeiträge auf Azure-Blog (bit.ly/1Y5T1SB), und befolgen Sie die @documentdb Twitter-Konto für Updates.


Julie Lerman ist Microsoft MVP, .NET-Mentor und Unternehmensberaterin. Sie lebt in den Bergen von Vermont. Sie hält bei User Groups und Konferenzen in der ganzen Welt Vorträge zum Thema Datenzugriff und anderen .NET-Themen. Julie Lerman führt unter thedatafarm.com/blog einen Blog. Sie ist die Autorin von „Programming Entity Framework“ sowie der Ausgaben „Code First“ und „DbContext“ (alle bei O’Reilly Media erschienen). Folgen Sie ihr auf Twitter: @julielerman und sehen ihre Pluralsight-Kurse unter juliel.me/PS-Videos.

Vielen Dank an den folgenden technischen Experten von Microsoft für die Überprüfung dieses Artikels: Andrew Liu