Ich arbeite derzeit in einem Projektteam an einer Anwendung, die einen Großteil ihrer Daten in CouchDB speichert. Eines der schönsten Dinge an Couch ist seine RESTful API. Alles ist einfaches HTTP und JSON, leicht zu verstehen und leicht zu programmieren.
Ein einfaches Beispiel
Dieses Skript liest eine CouchDB-Ansicht, die Dokumente auflistet, die wir loswerden wollen. In diesem Beispiel habe ich die Standardansicht
[sourcecode language="bash"]
#!/bin/sh
COUCH="https://xebia.com/blog:5984/dbname"
curl "${COUCH}/_all_docs&include_docs=true"
| ./format_delete_command.js
| curl --header 'Content-Type: application/json'
--header 'Accept: application/json'
-X POST --data-binary @- "${COUCH}/_bulk_docs"
| tr -d 'n' | jsonpp
[/sourcecode]
Für diejenigen, die mit curl nicht vertraut sind: Der Parameter -data-binary gibt den Körper der Anfrage an. Das @ -Zeichen zeigt an, dass das, was folgt, ein Dateiname ist. Um von stdin zu posten, verwenden Sie ein
[sourcecode language="javascript"]
{"total_rows":22,"offset":0,"rows":[
{"id":"123456","key":"123456","value":{"rev":"1-acf7f3..."},"doc":{...}},
{"id":"123457","key":"123457","value":{"rev":"1-b67df1..."},"doc":{...}}
...20 more...
]}
[/sourcecode]
Beachten Sie, dass das doc-Feld ausgelassen wird, es sei denn, Sie übergeben include_docs=true als Abfrageparameter. Um einen Massenlöschbefehl zu senden, senden wir dies:
[sourcecode language="javascript"]
{ "docs":[
{"_id":"123456","_rev":"1-acf6f39495a2cd4465be504cd435629e","_deleted":true}
{"_id":"123457","_rev":"1-b67df18954264dbb65be341294e572a5","_deleted":true}
...20 more...
]}
[/sourcecode]
awk hätte das erledigen können. Hier ist das JavaScript, das wir stattdessen verwenden:
[sourcecode language="javascript"]
#! /usr/bin/env node
var inputStream = process.stdin
, data = '';
process.stdin.resume();
// Read the entire input stream into the data variable.
inputStream.on('data', function(chunk) {
data += chunk;
});
// At end of stream, load the JSON object and process it.
inputStream.on('end', function() {
var json = JSON.parse(data)
, rows = json['rows']
, postdata = { docs: [] };
rows.forEach(function(row) {
var doc = row['doc'];
postdata.docs.push( {_id: doc._id, _rev: doc._rev, _deleted: true} );
});
console.log(JSON.stringify(postdata));
});
[/sourcecode]
Ein paar Dinge sind erwähnenswert:
- Node.js ist schlau genug, um die Hashbang-Zeile zu ignorieren.
- Wir puffern einfach die gesamte Eingabe in einer temporären Variable. Unsere Dokumente sind klein, wir brauchen keinen cleveren Streaming-Parser.
- Verwenden Sie console.log, um in den Standard-Out zu schreiben, console.warn, um in den Standard-Err zu schreiben. Sie können process.exit(int) verwenden, um sich mit einem Fehlercode zu beenden.
- Für diese spezielle Ansicht hatten wir id's und rev's in der Ausgabe der Ansicht und hätten daher den Löschbefehl ohne die Übergabe des Parameters include_docs formatieren können. Das liegt daran, dass ich für das Beispiel die Ansicht
_all_docs verwendet habe. Unsere tatsächlichen Ansichten haben unterschiedliche Ausgaben, und wenn Sie sich auf_all_docs verlassen, funktioniert das Skript mit allen von ihnen. (Bitte füttern Sie Ihre _all_docs-Ansicht nicht mit diesem Skript, löschen Sie einfach die Datenbank!)
Unsere anderen Skripte verwenden den gleichen Ansatz.
Zusammenfassung
Node.js wird so oft als Server bezeichnet, dass man leicht vergisst, dass man es auch in einer Shell-Pipeline verwenden kann. Dieser Beitrag zeigt Ihnen, wie Sie das tun können. Aktualisiert am 27.06.2012: Vielleicht möchten Sie sich meinen Folgebeitrag JSON Shell Scripting mit jsawk ansehen.
Verfasst von

Barend Garvelink
Contact



