4
Couchbase Lite On-‐device, lightweight, na1ve embedded JSON database
Sync Gateway Synchronize on-‐device
Couchbase Lite with Couchbase Server in the cloud
Couchbase Server High performance, scalable, always-‐on JSON database in
the cloud
Couchbase Mobile
7
Pluggable Authentication
JavaScript sync function runs on all mutations.
Data Partitioning – channel(…): Routes the document to the named channel
Data Access Control – Read!
– access(…): Grants access to a channel to a specified user, list of users, or a role – role(…): Grants a user a role
– Write!
– throw(…): Prevents a document mutation from persisting
– requireUser/Role/Access(…): Validates the user, their role assignments, or their access privileges.
Authentication, Partitioning, Access Control
Document Database Overview
• Semi-structured • Key-value pairs • Schemaless • JSON-backed • Very low-friction
Map Reduce Queries Overview
• Functional queries, instead of set-theoretic • Write query logic in pure C#, not SQL • Can be one-off, or auto-updating as data changes • You probably already know how to use it: – Map is like LINQ’s Select method – Reduce is like LINQ’s Aggregate method
Sync Overview
• Master-master replication • Uses HTTP + REST • Offline mode for free • Manual or continuous modes • Automatic retry on failure • Responds to network changes
Programming Model
• You: make your changes to docs • Queries: will reflect those changes • Replicators: sync changes for you
Opening a Database
var db = Manager.SharedInstance.GetDatabase("foo"); "Debug.Assert(db != null);" var db = Manager.SharedInstance.GetExistingDatabase("foo"); "Debug.Assert(db == null);"
Getting a Document
var doc = db.GetDocument("foo-doc"); "Debug.Assert(doc != null); ""var doc = db.GetExistingDocument("foo-doc"); "Debug.Assert(doc == null);
Updating a New Document
var rev = doc.CreateRevision(); "var props = new Dictionary<string, object> " { " { "foo", "bar"}, " { "fizz", "buzz"} " }; "rev.SetUserProperties(props); "rev.Save();
Updating an Existing Document
var props = doc.Properties; "var newProps = new Dictionary<string, object>(props) " { " { "foo", "bar"} " }; "doc.PutProperties(newProps); // Saves a new revision
Dealing with Changes
doc.Change += (sender, e) => "{ " // e.g. if we get a conflict... ! if (e.Change.IsConflict) " { " // we can resolve it! ! } "};
DocumentChange Members
String "Boolean "Boolean "String "
Uri "RevisionInternal"
"
DocumentId" IsConflict" IsCurrentRevision" RevisionId" SourceUrl" WinningRevision"
Handling Conflicts
var current = doc.CurrentRevision; "foreach(var rev in doc.ConflictingRevisions) "{ " var newRev = rev.CreateRevision(); " if (rev.Equals(current)) { " newRev.SetProperties(mergedProps); " } else { " newRev.IsDeletion = true; " } " newRev.Save(); "}
Auto-merging Properties using LINQ
Dictionary<string, object> mergedProps; "try "{ " mergedProps = doc.ConflictingRevisions" .SelectMany(rev => rev.UserProperties) " .Distinct() " .ToDictionary( " kvp => kvp.Key, " kvp => kvp.Value" ); "} catch (ArgumentException ex) { " // Merge conflict requires manual resolution. !}
Create a View
var view = db.GetView("foo"); "Debug.Assert(view != null); ""var view = db.GetExistingView("foo"); "Debug.Assert(view == null); "
Add a Map Function
view.SetMap((doc, emit) => "{ " var foo = (String)doc["foo"]; " if (foo.Equals("bar")) { " emit ("text", doc["text"]); " } "}, "1"); "
Using a Reduce Function
ReduceDelegate reducer = (keys, values, rereduce) => "{ " var i = 0; var wordCount = 0; " foreach(var key in keys) { " if (key == "text") { " var str = (String)values[i]; " wordCount += str.Split(' ').Length; " } " } " return wordCount; "}; "view.SetMapReduce(mapper, reducer, "1");"
Create a Query
var query = view.CreateQuery(); ""// Options, like..."query.Completed += (sender, e) => { " Log("Results: {0}", e.Rows); "}; "query.Descending = true; ""// Get records..."var rows = await query.RunAsync(); "rows.Where(row => ...);
Create a LiveQuery
var liveQuery = query.ToLiveQuery(); ""// Respond to changes in the view."liveQuery.Changed += (sender, e) => "{ " Log("Updates: {0}", e.Rows.Count); "};
Pull Replicator
var uri = new Uri(syncGatewayUrl); "var pull = db.CreatePullReplication(uri); "pull.Continuous = true; "pull.Changed += ReplicationChanged; "pull.Start();
Push Replicator
var uri = new Uri(syncGatewayUrl); "var push = db.CreatePushReplication(uri); "push.Continuous = true; "push.Changed += ReplicationChanged; "push.Start();
Top Related