Einführung CouchDB

  • View
    2.813

  • Download
    0

  • Category

    Business

Preview:

DESCRIPTION

Eine Übersicht über die Funktionen der CouchDB im Rahmen eines Vortrags an der Beuth Hochschule für Technik in Berlin.

Citation preview

COUCHDB

<- Achtet auf dieses Auto Oliver Kurowski, @okurow

Wer bin ich Dipl. Inf. (FH) Oliver Kurowski Studium Medieninformatik an der TFH-Berlin (Beuth

Hochschule für Technik) Abschluss 2003 (Dipl.)

Erster Computer: Apple II 1983 Seit 2003: KW automotive GmbH

Div. Fachartikel im PHP-Magazin 2012: Buch „CouchDB mit PHP“

(www.CouchDBmitPHP.de)

Twitter: @okurow Mail: oliver@thinkcouchdb.com

Oliver Kurowski, @okurow

ÜBERBLICK

Oliver Kurowski, @okurow

Was ist CouchDB?Eine NoSQL Datenbank

die Ihre Dokumente in JSON speichert,

JavaScript für MapReduce benutzt,

über HTTP angesprochen wird,

Multi-Master-Replikationen ermöglicht,

mit Attachments an Datendokumenten eigene Programme innerhalb der CouchDB erlaubt,

Und in Erlang geschrieben ist.

2005 Anfang der Entwicklung von Damien Katz, ehemaliger Lotus Notes Entwickler. Seit 2008 hauptberuflich.

Nov 2008: Apache Project

2012: Mit Couchbase ein neues kommerzielles Produkt

Oliver Kurowski, @okurow

Wo läuft CouchDB? Windows (binaries auf couchdb.apache.org) Lunux (Sourcecode auf der Hompage, diverse build-tools

erhältlich) Mac OSX Zum Testen: iriscouch.com / cloudant.com

Oliver Kurowski, @okurow

Übersicht der Funktionen Spricht HTTP Schemalose Dokumente im JSON-Format MVCC Multiversion Concurrency Control MapReduce zum Indizieren und Abfragen der Daten Transformationsfunktionen zum Anpassen der Ausgabe Replikationen mit Filtermöglichkeit Automatische/manuelle Funktionen beim Speichern von

Dokumenten Binäre Attachments für Dokumente Integrierte HTML-Oberfläche Futon

Oliver Kurowski, @okurow

VokabularCouchDB : Eine CouchDB installation

Datenbank: Eine Datenbank innerhalb einer CouchDB

Dokument: Ein Datensatz innerhalb einer Datenbank

Oliver Kurowski, @okurow

Dokumente in CouchDB Schemalos JSON

Keine Gruppierung von Dokumenten, daher Feld “doctype“

Oliver Kurowski, @okurow

{ “_id“: “1“, “_rev“: “1-axcv“, “doctype“: “fahrzeug“, “hersteller“: “Audi“, “modell“: “A3“, “baujahr“: 2000, “extras“: [“Alufelgen“,“Klimaanlage“]}

Kommunikation über HTTPREST API:

GET ruft Daten ab

PUT/POST sendet Daten

DELETE löscht einen Datensatz

COPY kopiert einen Datensatz

Auf der Kommandozeile mit curl:

Oliver Kurowski, @okurow

$ curl –X PUT http://localhost:5984/fahrzeuge/1 -d ‘{“doctype“:“fahrzeug“, “hersteller“:“Audi“, “modell“:“A3“}‘{“ok“:true, “id“:“1“, “rev“:“1-a4b7a34..“}

$ curl –X PUT http://localhost:5984/fahrzeuge {“ok“:true}

$ curl –X GET http://localhost:5984/fahrzeuge/1 {“_id“:“1“, “_rev“: “1-a4b7a34..“, “doctype“: “fahrzeug“, “hersteller“: “Audi“,“modell“: “A3“}

$ curl –X GET http://localhost:5984/fahrzeuge/2{“error“:“not found“, “reason“:“missing“}

MVCC

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlMVCC ermöglicht nichtblockierendes Schreiben auf eine Datenbank.Die neue Version eines Dokuments wird an die alte Version angehangen.Dabei erhöht sich die Revisionsnummer des Dokuments.

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlMVCC ermöglicht nichtblockierendes Schreiben auf eine Datenbank.Die neue Version eines Dokuments wird an die alte Version angehangen.Dabei erhöht sich die Revisionsnummer des Dokuments.

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlMVCC ermöglicht nichtblockierendes Schreiben auf eine Datenbank.Die neue Version eines Dokuments wird an die alte Version angehangen.Dabei erhöht sich die Revisionsnummer des Dokuments.

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlMVCC ermöglicht nichtblockierendes Schreiben auf eine Datenbank.Die neue Version eines Dokuments wird an die alte Version angehangen.Dabei erhöht sich die Revisionsnummer des Dokuments.

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlMVCC ermöglicht nichtblockierendes Schreiben auf eine Datenbank.Die neue Version eines Dokuments wird an die alte Version angehangen.Dabei erhöht sich die Revisionsnummer des Dokuments.

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlBei gleichzeitiger Bearbeitung eines Dokuments „gewinnt“ derjenige, der es zuerst speichert. Dadurch erhöht sich die Revisionsnummer des Dokuments, und der Langsamere hat damit eine überholte Revisionsnummer, das Speichern wird abgelehnt

Oliver Kurowski, @okurow

MVCC – Multiversion Concurrency ControlDie Revisionsnummer eines Dokuments wird von der CouchDB gesetzt.

Jede Änderung eines Dokuments muss mit der aktuellen Revisionsnummer angegeben werden.

Oliver Kurowski, @okurow

$ curl –X PUT http://localhost:5984/fahrzeuge/1 -d ‘{“doctype“:“fahrzeug“, “hersteller“:“Audi“, “modell“:“A3“, “baujahr“:2000, “_rev“:“1-a4b7a34..“}‘{“ok“:true, “id“:“1“, “rev“:“2-7c45a..“}

$ curl –X DELETE http://localhost:5984/fahrzeuge/1?rev=2-7c45a..{“ok“:true, “id“:“1“, “rev“:“3-e94x..“}

$ curl –X PUT http://localhost:5984/fahrzeuge/1 -d ‘{“doctype“:“fahrzeug“, “hersteller“:“Audi“, “modell“:“A3“, “baujahr“:2000“}‘{“error“:“conflict“, “reason“:“Document update conflict“}

$ curl –X GET http://localhost:5984/fahrzeuge/1{“error“:“not found“, “reason“:“deleted“}

ABFRAGEN

Oliver Kurowski, @okurow

ViewsEine View ist ein Container für eine Map- und optional Reduce Funktion.

Standardmäßig sind die Funktionen in JavaScript geschrieben,andere Sprachen können aber eingestellt werden.

Views können Daten Filtern Gruppieren Auswerten

Oliver Kurowski, @okurow

Views Views werden innerhalb spezieller Dokumente (Designdokumente) in einer Datenbank gespeichert, und wie Datendokemente abgerufen:

Bsp: http://localhost:5984/fahrzeugDatenbank/_design/abfragen/_view/nachHersteller

Oliver Kurowski, @okurow

{ “_id“: “_design/abfragen“, “_rev“: “1-e7fg“, “views“: { “nachHersteller“: { “map“:“function(doc) {…}“, “reduce“:“function(keys,values) {…}“ } }}

Die Map-FunktionHat ein einzelnes Dokument als Input

Kann Key/Value Paare ausgeben. Dabei können die Werte aus allen JSON-Typen bestehen:

- Spezialwerte: null, true, false- Zahlen: 1e-17, 1.5, 200- Strings : “+“, “1“, “Ab“, “Audi“

- Arrays: [1], [1,2], [1,“Audi“,true]

- Objekte: {“price“:1300,“sold“:true}

Die Ausgegebenen Key/Value Paare aller Dokumente werden in einer Liste gespeichert,die nach den Werten der Keys aufsteigend sortiert ist.

Zusätzlich zu jedem Key/Value paar wird auch die Dokument-ID ausgegeben

Oliver Kurowski, @okurow

Die Map-Funktion Beispiel

Oliver Kurowski, @okurow

Datendokumente:

Map-Funktion in JavaScript in einer View “nachPreis“:

Ergebnis von _view/nachPreis:

Id: 2hersteller : Audimodell: A4baujahr : 2009preis: 16.000

Id: 1hersteller: Audimodell: A3baujahr: 2000preis: 5.400

Id: 3hersteller : VWmodell: Golfbaujahr : 2009preis: 15.000

Id: 4hersteller : VWmodell: Golfbaujahr : 2008preis: 9.000

Id: 5hersteller : VWmodell: Polobaujahr : 2010preis: 12.000

„nachPreis“: { “map“:“function(doc) { emit (doc.preis, doc.hersteller+‘-‘+doc.modell+‘-‘+doc.baujahr); }“}

{"total_rows":5,"offset":0,"rows":[ {"id":"1","key":5.400,"value":“Audi-A3-2000“}, {"id":"2","key":9.000,"value":“VW-Golf-2008“}, {"id":"3","key":12.000,"value":“VW-Polo-2010“}, {"id":"4","key":15.000,"value":“VW-Golf-2009“}, {"id":"5","key":16.000,"value":“Audi-A4-2009“} ]}

Die Map-Funktion steuern

Oliver Kurowski, @okurow

Zur Abfragezeit kann die Ausgabe eine View beeinflusst werden:

_view/nachPreis?key=9.000

_view/nachPreis?endkey=10.000

_view/nachPreis?startkey=10.000&endkey=15.500

{"total_rows":5,"offset":1,"rows":[ {"id":"2","key":9.000,"value":“VW-Golf-2008“},]}

{"total_rows":5,"offset":0,"rows":[ {"id":"1","key":5.400,"value":“Audi-A3-2000“}, {"id":"2","key":9.000,"value":“VW-Golf-2008“},]}

{"total_rows":5,"offset":2,"rows":[ {"id":"3","key":12.000,"value":“VW-Polo-2010“}, {"id":"4","key":15.000,"value":“VW-Golf-2009“} ]}

Die Reduce-Funktion Hat die Ergebnisse aus der Map-Phase als Input Soll diese Liste auf einen einzelnen Wert reduzieren Wird nach der Map-Phase automatisch ausgeführt

Oliver Kurowski, @okurow

Die Reduce-Funktion BeispielErweiterung der View „nachPreis“

Ergebnis von _view/nachPreis:

_view/nachPreis?endkey=10.000

Oliver Kurowski, @okurow

„nachPreis“: { “map“:“function(doc) { emit (doc.preis, doc.hersteller+‘-‘+doc.modell+‘-‘+doc.baujahr); }“, “reduce“:“function(keys,values) { return (count(values) ); //_count }“ }}

{"rows":[ {"key":null, "value":5 } ]}

{"rows":[ {"key":null, "value":2 } ]}

View Parameter limit: Begrenzt die Anzahl der Ergebnisse skip: Überspringt eine Anzahl von Egebnissen include_docs=true: Ohne Reduce-Phase wird das

entsprechende Dokument zusätzlich zu jeder Zeile der Map-Liste ausgegeben

key, startkey,endkey: Bestimme Keys, bzw. Bereiche liefern startkey_docid=x: Nur Dokumente mit der id>=x endkey_docid=x: Nur Dokumente mit der id<x descending=true: Umgekehrte Sortierreihenfolge (!) stale=ok: Zeige die gespeicherten Werte, kein Aufruf der View stale=update_after: Zeige die gespeicherten Werte, danach

Aufruf der View und Durchlauf MapReduce Phase group, group_level,reduce=false: Gruppierungen der Keys,

sofern Arrays

Oliver Kurowski, @okurow

Oliver Kurowski, @okurow

DEMO MAPREDUCE IN FUTON

TRANSFORMATION

Oliver Kurowski, @okurow

Transformationsfunktionen Dokumente sind JSON Objekte

Ergebnisse von Views sind ebenfalls JSON Objekte

CouchDB kann Serverseitig diese Daten formatiert liefern.

Shows: Transformationen für Datendokumente

Lists: Transformationen für Views

Shows und Lists werden zur Abfragezeit verarbeitet, d.h. bei großen Datenmengen einen erheblichen Zeitaufwand.

Oliver Kurowski, @okurow

Shows: Dokumente transformieren

Oliver Kurowski, @okurow

{“Id“: “1“,“hersteller“: “Audi“,“modell“: “A3“,“baujahr“: 2000,“preis“: 5.400}

Datendokument (JSON): Show-Funktion in dem Designdokument:

Ergebnis von _show/inHTML/1 :

“shows“: { “inHTML“:“function(doc,req) { var outS=‘‘; outS=‘<b>‘+doc.hersteller+‘ ‘+doc.modell+‘</b><br>`; outS+=‘Baujahr: ‘+doc.baujahr+‘<br>‘; outS+=‘Preis: ‘+doc.preis; return outS; }“ }

Audi A3Baujahr: 2000Preis: 5.400

List: Views transformierenErgebnis einer View nachPreis: List-Funktion in dem Designdokument:

Ergebnis von _list/alsLi/nachPreis :

Alle Steuerfunktionen einer View sind auch hier benutzbar

Oliver Kurowski, @okurow

“lists“: { “alsLI “:“function(head,req) { start({'code':200,'headers':{'Content-Type':'text/html'}}); while(row=getRow()) { send(‘<li>‘+row.value+‘ :‘ +row.key+‘</li>‘); } }“}

• Audi-A3-2000 : 5.400• VW-Golf-2008 : 9.000• VW-Polo-2010 :

12.000• VW-Golf-2009 :

15.000• Audi-A4-2009 :

16.000

{"total_rows":5,"offset":0,"rows":[ {"id":"1","key":5.400,"value":“Audi-A3-2000“}, {"id":"2","key":9.000,"value":“VW-Golf-2008“}, {"id":"3","key":12.000,"value":“VW-Polo-2010“}, {"id":"4","key":15.000,"value":“VW-Golf-2009“}, {"id":"5","key":16.000,"value":“Audi-A4-2009“} ]}

Das Request ObjektShows und Lists haben Zugriff auf das Request Objekt mit folgenden Feldern:

(die Interessantesten)

Info: Informationen über die DatenbankId: übergebene Dokument ID (null, wenn keine übergeben wurde)requested_path: Der Aufruf in Einzelteilen, wie er gesendet wurdeheaders: Vom Client gesendeter HeaderuserCTX: Informationen über den angemeldeten Benutzerquery: angehangene Parameter

Das Feld req.query erlaubt das Hinzufügen eigener Parameter an eine Abfrage zum Steuern der Show/List.Bsp: _show/inHTML/1?zeigePreis=true

Abfrage In der show-Funktion:Oliver Kurowski, @okurow

if(req.query.zeigePreis==true) { ….}

SPEICHERFUNKTIONEN

Oliver Kurowski, @okurow

Funktionen beim Speichernvalidate_doc_update Automatische Validierung beim Speichern, kann Speichern

verhindern Funktionen werden automatisch aufgerufen Pro Designdokument nur eine Funktion Beim Speichern werden die Funktionen aller Designdokumente

einer Datenbank durchlaufen

Oliver Kurowski, @okurow

Funktionen beim Speichernvalidate_doc_update Eingabgsparameter: Das neues Dokument eventuell vorhandenes Dokument mit der angegebenen ID UserContext

Oliver Kurowski, @okurow

function (newDoc,oldDoc,userCTX) { if(!newDoc.name || newDoc.name==‘‘) { throw ({ forbidden:‘Kein Name angegeben‘}); }}

function (newDoc,oldDoc,userCTX) { if(newDoc.name != oldDoc.name) { throw ({ forbidden:‘Name darf nicht verändert werden‘}); }}

function (newDoc,oldDoc,userCTX) { if(userCTX.name !=‘oliver‘ ) { throw ({ forbidden:‘Nur User oliver darf Daten schreiben‘}); }}

Funktionen beim Speichernupdate Datendokumente vor dem Speichern verändern, bzw.

Speichern verhindern expliziter Aufruf pro Speichervorgang Mehrere Funktionen in einem Designdokument Aber nur eine Funktion pro Speichervorgang auswählbar

Oliver Kurowski, @okurow

Funktionen beim Speichernupdate Eingabgsparameter: eventuell vorhandenes Dokument mit der angegebenen ID request (mit neuen Daten im body-Feld)

Ermöglicht einfache Operationen auf Datendokumente, ohne die Dokumente vorher zu laden:

Datendokument: update-Funktion:

Aufruf:

Oliver Kurowski, @okurow

function (doc,req) { if(doc!=null) { doc.stimmen+=1; return ({doc, ‘Anzahl der Stimmen:‘+doc.stimmen]); }else{ return ({null,‘Person ‘+req.id+‘ nicht gefunden‘})}

{ “_id“:“oliver“, “stimmen“:0}

$ curl –X PUT http://localhost:5984/personen/_design/operationen/update/pluseins/oliverAnzahl Stimmen: 1

$ curl –X PUT http://localhost:5984/personen/_design/operationen/update/pluseins/oliPerson oli nicht gefunden

ATTACHMENTS

Oliver Kurowski, @okurow

AttachmentsAn bestehende Dokumente können Binärdaten angehangen werden

Große Dateien (Video, MP3) können ausschnittsweise geladen werden

Abrufen der Datei über die URL des Datendokuments:

http://localhost:5984/fahrzeuge/1/bild.jpg

http://localhost:5984/homepage/de/index.html

Das „/“ kann ein Teil des Dokumentnamens sein, dadurch Baumstruktur möglichhttp://localhost:5984/homepage/de/bilder/1.jpg

Oliver Kurowski, @okurow

AttachmentsErzeugen einer neuen Datenbank und leeren Datensatzes:

Lokale Datei intex.html als Attachment speichern

Aufruf im Browser:

Oliver Kurowski, @okurow

$ curl -X PUT http://localhost:5984/websites{“ok“:true}

$ curl -X PUT http://localhost:5984/websites/de -d‘{}‘{"ok":true,"id":"de","rev":"1-967a00dff5e02add41819138abb3284d"}

$ curl -X PUT http://localhost:5984/websites/de/index.html?rev=1-967a00dff5e02add41819138abb3284d -d @index.html -H “Content-type:text/html“{"ok":true,"id":"de","rev":"2-f3f26739438d8f95570669c8fc886164"}

http://localhost:5984/websites/de/index.html

REPLIKATION

Oliver Kurowski, @okurow

Replikation

Oliver Kurowski, @okurow

Master-Client

Datenbank a Datenbank b

Replikation

Oliver Kurowski, @okurow

Datenbank a Datenbank b

Master-Master

Replikation

Oliver Kurowski, @okurow

Datenbank a Datenbank b

Datenbank c

Master-Master-Client

Replikation

Oliver Kurowski, @okurow

Datenbank a Datenbank b

Datenbank cDatenbank e

Datenbank f

Datenbank g

Multi-Master

Replikation

Oliver Kurowski, @okurow

Daten werden immer nur in eine Richtung Abgeglichenpull: Datenbank holt sich die Datenpush: Datenbank schickt Daten

Bei Master-Master: 2 gegenseitige Replikationen

Es werden nur Änderungen von Dokumenten verglichen (_changes Feed), d.h. wenn ein Dokument auf dem Client vorhanden ist, und auf dem Master nicht, wird das Client-Dokument bei der Replikation nicht gelöscht.

Verglichen werden nur die Revisionsnummern. Höhere Revisionsnummer des Dokuments beim Master = Client wird aktualisiert.

Ein gelöschtes Dokument bleibt weiterhin in der Datenbank. Löschen ist eine Änderung an einem Dokument (_deleted:true), und gelöschte Dokumente werden repliziert.

Replikation

Oliver Kurowski, @okurow

Start einer Replikation über POST Befehl an _replicate

$ curl -X POST http://localhost:5984/_replicate -H "Content-type:application/json" -d '{"source":"datenbank_a","target":"datenbank_b"}'{"ok":true,"session_id":"b4ecde6f3b4a3948e51a409894b18a5c","source_last_seq":1,"replication_id_version":2,"history":[{"session_id":"b4ecde6f3b4a3948e51a409894b18a5c","start_time":„Sun, 10 Jun 2012 09:55:16 GMT","end_time":„Sun, 10 Jun 2012 09:55:16 GMT","start_last_seq":0,"end_last_seq":1,"recorded_seq":1,"missing_checked":1,"missing_found":1,"docs_read":1,"docs_written":1,"doc_write_failures":0}]}

Replikation

Oliver Kurowski, @okurow

Oder durch Eintrag in die _replicator Datenbank

Dieses Dokument nach der Replikation:

$ curl -X PUT http://localhost:5984/_replicator/einmalig -d {"source":"datenbank_a","target":"datenbank_b"}' {"ok":true,"id":"einmalig","rev":"1-57c8e9e3949e9fa48c135f8cdae3d88e"}

{ "_id": "einmalig", "_rev": "3-4700e5caef6496219e032322427bca43", "source": "datenbank_a", "target": "datenbank_b", "owner": null, "_replication_state": "completed", "_replication_state_time": "2012-06-10T03:05:35-07:00", "_replication_id": "44534eb9bb71658fe1698fc69d62f88b", "_replication_stats": { "revisions_checked": 2, "missing_revisions_found": 1, "docs_read": 1, "docs_written": 1, "doc_write_failures": 0, "checkpointed_source_seq": 3 } }

Replikation

Oliver Kurowski, @okurow

Besonderheiten bei Replikationen:

Continuous Replication: Replikationen müssen nicht einzeln angestoßen werden, Änderungen werden kontinuierlich weitergegeben

Named Document Replication:Nur einzeln benannte Dokumente werden repliziert

Auch Designdokumente können repliziert werden. Bei Verwendung von Applikation in der CouchDB einfaches Deployment der App über viele Datenbanken automatisch möglich.

Replikation

Oliver Kurowski, @okurow

Ein Highlight:

Filtered Replication: Eine Funktion erlaubt/ verhindert die Replikation von Dokumenten{

“_id“:“_design/filterfunktionen“, “filters“: { “ab18“:“function(doc,req) { if(doc.alter && doc.alter>17) { return true; } else { return false; } }“ }}

$ curl -X PUT http://localhost:5984/_replicator/einmalig -d {"source":"datenbank_a","target":"datenbank_b“, “filter”:”filterfunktionen/ab18”}'

Oliver Kurowski, @okurow

LINKS (RECHTS)

http://CouchDBmitPHP.de

http://apache.couchdb.org

http://berlin.couchdb.org

Irc: #couchdb