View
123
Download
2
Category
Preview:
Citation preview
COUCHBASE LITE IN-‐DEPTH
James Nocentini, Developer Advocate, Couchbase
©2014 Couchbase Inc.
This morning
▪Using Documents and Revisions
▪Utilising convenience Data Model APIs
▪ Creating Couchbase Lite Views
▪Querying Views
▪ Live Queries
2
ToDo Lite
©2014 Couchbase Inc. 4
Demo
©2014 Couchbase Inc.
Data Model
6
©2014 Couchbase Inc. 7©2015&Couchbase&Inc.
Overview
▪ Couchbase&Mobile&features&▪ Focus&on&Couchbase&Lite:&▪ Installing&and&running&a&sample&app&▪ A&tour&of&Couchbase&Lite’s&architecture&and&API&▪…as&shown&in&the&sample&app’s&code&▪Next&steps
2
1. Database
©2014 Couchbase Inc. 9©2015&Couchbase&Inc.
InitializationDemoAppDelegate.m:61
!!!!//"Initialize"Couchbase"Lite"and"find/create"my"database:!!!!!NSError*!error;!!!!!self.database!=![[CBLManager!sharedInstance]!createDatabaseNamed:!kDatabaseName!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!error:!&error];!!!!!if!(!self.database)!{!!!!!!!!![self!showAlert:!@"Couldn't!open!database"!error:!error!fatal:!YES];!!!!!!!!!return!NO;!!!!!}!
18
©2014 Couchbase Inc.
Database
10
public class Application extends android.app.Application {
@Overridepublic void onCreate() { super.onCreate(); }
}
©2014 Couchbase Inc.
Database
11
public class Application extends android.app.Application {
@Overridepublic void onCreate() { super.onCreate(); Manager manager = new Manager(new AndroidContext(getApplicationContext()), Manager.DEFAULT_OPTIONS); }
}
©2014 Couchbase Inc.
Database
12
public class Application extends android.app.Application {
@Overridepublic void onCreate() { super.onCreate(); Manager manager = new Manager(new AndroidContext(getApplicationContext()), Manager.DEFAULT_OPTIONS); Database database = manager.getDatabase("dbname");}
}
©2014 Couchbase Inc. 13©2015&Couchbase&Inc.
Manager
▪ TopJlevel&object,&usually&a&singleton&▪ A&collection&of&named&databases&▪ Locates&databases&in&filesystem
19
©2014 Couchbase Inc. 14©2015&Couchbase&Inc.
Database
▪Namespace&for&documents&▪ Contains&views&and&their&indexes&▪ Contains&validation&functions&▪ Source&and&target&of&replication
21
©2014 Couchbase Inc.
Database
15
©2014 Couchbase Inc. 16©2015&Couchbase&Inc.
Interesting+Document+Facts
▪ JSON&allows&nested&data&structures&(arrays,&maps)&
▪ Schemaless&—&Documents&needn’t&have&the&same&structure&
▪Different&types&of&docs&can&coexist&in&a&database&▪ “type”&property&is&a&common&convention&
▪Documents&are&versioned&
▪Optimistic&concurrency&control&(MVCC)
22
©2014 Couchbase Inc.
Documents
17
Map<String, Object> properties = new HashMap<String, Object>();properties.put("type", "list");properties.put("title", title);properties.put("created_at", currentTimeString);properties.put("owner", "profile:" + userId);properties.put("members", new ArrayList<String>());
©2014 Couchbase Inc.
Documents
18
Map<String, Object> properties = new HashMap<String, Object>();properties.put("type", "list");properties.put("title", title);properties.put("created_at", currentTimeString);properties.put("owner", "profile:" + userId);properties.put("members", new ArrayList<String>());
Document document = database.createDocument();
©2014 Couchbase Inc.
Documents
19
Map<String, Object> properties = new HashMap<String, Object>();properties.put("type", "list");properties.put("title", title);properties.put("created_at", currentTimeString);properties.put("owner", "profile:" + userId);properties.put("members", new ArrayList<String>());
Document document = database.createDocument();document.putProperties(properties);
©2014 Couchbase Inc.
Documents
20
Document document = database.getDocument("task-123");
©2014 Couchbase Inc.
Documents
21
Document document = database.getDocument("task-123");String title = document.getProperty("title");
©2014 Couchbase Inc.
Documents
22
Document document = database.getDocument("task-123");String title = document.getProperty("title");Map<String, Object> properties = doc.getProperties();String owner = (String) properties.get("owner");
©2014 Couchbase Inc.
Documents
{ "_id": "123", "type": "list", "title": "Today’s list", "owner": "1234567890", "members": [
"0987654321","0192837465"
]}
23
Models
©2014 Couchbase Inc.
Models
25
@interface Task : CBLModel
@end
@implementation Task
@end
©2014 Couchbase Inc.
Models
26
@interface Task : CBLModel
@property NSString *title;
@end
@implementation Task @dynamic title;
@end
©2014 Couchbase Inc.
Models
27
@interface Task : CBLModel
@property NSString *title; @property bool checked;
@end
@implementation Task @dynamic title, checked;
@end
©2014 Couchbase Inc.
Models
28
@interface Task : CBLModel
@property NSString *title; @property bool checked; @property (weak) List *list_id;
@end
@implementation Task @dynamic title, checked, list_id;
@end
©2014 Couchbase Inc.
Models
29
Task *task = [Task modelForNewDocumentInDatabase:self.database];
New model
New model for
Saving the model
[task save:nil];
Task *task = [Task modelForDocument:self.database];
©2015 Couchbase Inc. ‹#›
©2014 Couchbase Inc. 31
2.+Views+&+Queries
©2014 Couchbase Inc. 32©2015&Couchbase&Inc.
Creating+A+Database+ViewRootViewController.m:50
!!!!//"Define"a"view"with"a"map"function"that"indexes"toAdo"items"by"creation"date:!!!!![[theDatabase!viewNamed:!@"byDate"]!setMapBlock:!MAPBLOCK({!!!!!!!!!id!date!=!doc[@"created_at"];!!!!!!!!!if!(date)!!!!!!!!!!!!!emit(date,!doc);!!!!!})!version:!@"1.1"];!
Not a UIView — a database “view” is like an index.
25
©2014 Couchbase Inc. 33©2015&Couchbase&Inc.
Map/Reduce+Views
▪ Concept&from&functional&programming,&via&Google&
▪ AppJdefined&map+function&operates&on&documents&
▪ doc&&⟼&&{&(key,&value)&…}&
▪ Its&output&generates&an&index&ordered&by&key&▪ Index&rows&can&be&aggregated&by&a&reduce+function+▪ Index&is&queried&by&key&or&key&range
26
©2014 Couchbase Inc. 34©2015&Couchbase&Inc.
Map/Reduce+Indexing
!!!!!!!
emit(doc.created,!!!!!!doc.title)
key value docID
“2013D03D12” “taxes” “doc17”
“2013D09D30” “call)mom” “doc62”
“2013D10D17” “cat)food” “doc82”
“2013D10D17” “tea)bags” “doc83”
“2013D10D22” “upgrade” “doc90”
index
all documents
map function
View+“byDate”
27
©2014 Couchbase Inc. 35©2015&Couchbase&Inc.
Creating+A+Database+ViewRootViewController.m:101
!!!!//"Define"a"view"with"a"map"function"that"indexes"toAdo"items"by"creation"date:!!!!![[theDatabase!viewNamed:!@"byDate"]!setMapBlock:!MAPBLOCK({!!!!!!!!!id!date!=!doc[@"created_at"];!!!!!!!!!if!(date)!!!!!!!!!!!!!emit(date,!nil);!!!!!})!version:!@"1.1"];!
Not a UIView — a database “view” is like an index.
28
©2014 Couchbase Inc. 36©2015&Couchbase&Inc.
Driving+the+Table+from+a+View+QueryRootViewController.m:101
!!!!//"Create"a"query"sorted"by"descending"date,"i.e."newest"items"first:!!!!!CBLLiveQuery*!query!=![[[database!viewNamed:@"byDate"]!query]!asLiveQuery];!!!!!query.descending!=!YES;!
!!!!//"Plug"the"query"into"the"CBLUITableSource,"which"uses"it"to"drive"the"table.!!!!!//"(The"CBLUITableSource"uses"KVO"to"observe"the"query's".rows"property.)!!!!!self.dataSource.query!=!query;!!!!!self.dataSource.labelProperty!=!@"text";"
@property(nonatomic,!strong)!IBOutlet!UITableView!*tableView;!@property(nonatomic,!strong)!IBOutlet!CBLUITableSource*!dataSource;
RootViewController.h:41
29
©2014 Couchbase Inc. 37©2015&Couchbase&Inc.
LiveQuery
Querying+a+View
30
key value docID
“2013D03D12” “taxes” “doc17”
“2013D09D30” “call)mom” “doc62”
“2013D10D17” “cat)food” “doc82”
“2013D10D17” “tea)bags” “doc83”
“2013D10D22” “upgrade” “doc90”
index
} Query QueryRowQueryRowQueryRow
.limit&=&3&
.offset&=&…&
.reverse&=&…&
.startKey&=&…&
.endKey&=&…
"
"
©2014 Couchbase Inc. 38©2015&Couchbase&Inc.
LiveQuery+Driving+A+GUI+Table
31
LiveQuery
QueryCBLUITableN
Source
UITableView
Your+Controller
! data source
delegate
Note:&CBLUITableSource&is&iOSJonly
©2014 Couchbase Inc. 39©2015&Couchbase&Inc.
LiveQuery+Driving+A+GUI+Table
32
©2014 Couchbase Inc. 40©2015&Couchbase&Inc.
Driving+the+Table+from+a+View+QueryRootViewController.m:101
!!!!//"Create"a"query"sorted"by"descending"date,"i.e."newest"items"first:!!!!!CBLLiveQuery*!query!=![[[database!viewNamed:@"byDate"]!query]!asLiveQuery];!!!!!query.descending!=!YES;!
!!!!//"Plug"the"query"into"the"CBLUITableSource,"which"uses"it"to"drive"the"table.!!!!!//"(The"CBLUITableSource"uses"KVO"to"observe"the"query's".rows"property.)!!!!!self.dataSource.query!=!query;!!!!!self.dataSource.labelProperty!=!@"text";"
@property(nonatomic,!strong)!IBOutlet!UITableView!*tableView;!@property(nonatomic,!strong)!IBOutlet!CBLUITableSource*!dataSource;
RootViewController.h:41
33
©2014 Couchbase Inc. 41©2015&Couchbase&Inc.
Displaying+Table+CellsDemoAppDelegate.m:131W!(void)couchTableSource:(CBLUITableSource*)source!
!!!!!!!!!!!!!!willUseCell:(UITableViewCell*)cell!!!!!!!!!!!!!!!!!!!!forRow:(CBLQueryRow*)row!{!!!!!//"Set"the"cell"background"and"font:!!!!!………!!!!!!!!!!//"Configure"the"cell"contents."Map"function"(above)"copies"the"doc"properties!!!!!//"into"its"value,"so"we"can"read"them"without"having"to"load"the"document.!!!!!NSDictionary*!rowValue!=!row.value;!!!!!BOOL!checked!=![rowValue[@"check"]!boolValue];!!!!!if!(checked)!{!!!!!!!!!cell.textLabel.textColor!=![UIColor!grayColor];!!!!!!!!!cell.imageView.image!=![UIImage!imageNamed:@"checked"];!!!!!}!else!{!!!!!!!!!cell.textLabel.textColor!=![UIColor!blackColor];!!!!!!!!!cell.imageView.image!=![UIImage!imageNamed:!@"unchecked"];!!!!!}!!!!!//"cell.textLabel.text"is"already"set,"thanks"to"setting"up"labelProperty!}
34
Called by the CBLUITableSource when it’s told to display a cell.
©2014 Couchbase Inc. 42©2015&Couchbase&Inc.
Responding+To+TapsDemoAppDelegate.m:131
W!(void)tableView:(UITableView!*)tableView!!!!!!!!!!!didSelectRowAtIndexPath:(NSIndexPath!*)indexPath!{!!!!!//"Ask"CBLUITableSource"for"the"corresponding"query"row,"and"get"its"document:!!!!!CBLQueryRow!*row!=![self.dataSource!rowAtIndex:indexPath.row];!!!!!CBLDocument!*doc!=!row.document;!
!!!!//"Toggle"the"document's"'checked'"property:!!!!!NSMutableDictionary!*docContent!=![doc.properties!mutableCopy];!!!!!BOOL!wasChecked!=![docContent[@"check"]!boolValue];!!!!!docContent[@"check"]!=!@(!wasChecked);!
!!!!//"Save"changes:!!!!!NSError*!error;!!!!!if!(![doc.currentRevision!putProperties:!docContent!error:!&error])!{!!!!!!!!![self!showErrorAlert:!@"Failed!to!update!item"!forError:!error];!!!!!}!}!
35
Called by the UITableView itself
©2014 Couchbase Inc. 43©2015&Couchbase&Inc.
Change+Notifications
▪ Three&types:&▪DatabaseChanged:&Any&document&updated&▪DocumentChanged:&A&specific&document&updated&▪ LiveQuery:&Change&in&query&result&set&▪ Enables&reactive&programming
ControllerModel&
(Database)GUI&View
User&event Update&doc
DocumentChangedRedraw
36
Index
©2014 Couchbase Inc.
Map/Reduce Index
45
@interface List : CBLModel
@property NSString *title;
+ (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db;
@end
@implementation Task @dynamic title;
+ (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { // ... }
@end
©2014 Couchbase Inc.
Map/Reduce Index
46
+ (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db {
}
©2014 Couchbase Inc.
Map/Reduce Index
47
+ (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { CBLView* view = [db viewNamed: @"lists"]; if (!view.mapBlock) {
} return [view createQuery]; }
©2014 Couchbase Inc.
Map/Reduce Index
48
+ (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { CBLView* view = [db viewNamed: @"lists"]; if (!view.mapBlock) { [view setMapBlock: MAPBLOCK({
}) reduceBlock: nil version: @"1"]; } return [view createQuery]; }
©2014 Couchbase Inc.
Map/Reduce Index
49
+ (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { CBLView* view = [db viewNamed: @"lists"]; if (!view.mapBlock) { [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString:@"list"]) emit(doc[@"title"], nil); }) reduceBlock: nil version: @"1"]; } return [view createQuery]; }
©2014 Couchbase Inc.
Map/Reduce Index
50
- (CBLQuery*) queryTasks { CBLView* view = [self.document.database viewNamed: @"tasksByDate"]; if (!view.mapBlock) { [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString: @"task"]) { } }) reduceBlock: nil version: @"4"]; } CBLQuery* query = [view createQuery]; return query; }
©2014 Couchbase Inc.
Map/Reduce Index
51
- (CBLQuery*) queryTasks { CBLView* view = [self.document.database viewNamed: @"tasksByDate"]; if (!view.mapBlock) { [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString: @"task"]) { id date = doc[@"created_at"]; NSString* listID = doc[@"list_id"]; emit(@[listID, date], doc); } }) reduceBlock: nil version: @"4"]; } CBLQuery* query = [view createQuery]; return query; }
©2014 Couchbase Inc.
Map/Reduce Index
52
- (CBLQuery*) queryTasks { CBLView* view = [self.document.database viewNamed: @"tasksByDate"]; if (!view.mapBlock) { [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString: @"task"]) { id date = doc[@"created_at"]; NSString* listID = doc[@"list_id"]; emit(@[listID, date], doc); } }) reduceBlock: nil version: @"4"]; } CBLQuery* query = [view createQuery]; NSString* listId = self.document.documentID; return query; }
©2014 Couchbase Inc.
Map/Reduce Index
53
- (CBLQuery*) queryTasks { CBLView* view = [self.document.database viewNamed: @"tasksByDate"]; if (!view.mapBlock) { [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString: @"task"]) { id date = doc[@"created_at"]; NSString* listID = doc[@"list_id"]; emit(@[listID, date], doc); } }) reduceBlock: nil version: @"4"]; } CBLQuery* query = [view createQuery]; NSString* listId = self.document.documentID; query.startKey = @[listId]; query.endKey = @[listId, @{}]; return query; }
©2015 Couchbase Inc. ‹#›
Query
©2014 Couchbase Inc.
Query
56
Query query = database.getView("tasksByDate").createQuery();
QueryEnumerator result = query.run();for (Iterator<QueryRow> it = result; it.hasNext(); ) { // do something}
©2014 Couchbase Inc.
Query
57
LiveQuery liveQuery = database.getView("tasksByDate").createQuery().toLiveQuery();
©2014 Couchbase Inc.
Query
58
LiveQuery liveQuery = database.getView("tasksByDate").createQuery().toLiveQuery();liveQuery.addChangeListener(new LiveQuery.ChangeListener() { @Override public void changed(LiveQuery.ChangeEvent event) { // update the UI } });
©2014 Couchbase Inc.
Query
59
©2015 Couchbase Inc. ‹#›
Attachments
©2014 Couchbase Inc.
Attachments
62
protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { InputStream stream = getContentResolver().openInputStream(data.getData()); }}
©2014 Couchbase Inc.
Attachments
63
protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { InputStream stream = getContentResolver().openInputStream(data.getData()); Document document = database.getDocument("task-123"); }}
©2014 Couchbase Inc.
Attachments
64
protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { InputStream stream = getContentResolver().openInputStream(data.getData()); Document document = database.getDocument("task-123"); UnsavedRevision newRevision = document.getCurrentRevision().createRevision(); }}
©2014 Couchbase Inc.
Attachments
65
protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { InputStream stream = getContentResolver().openInputStream(data.getData()); Document document = database.getDocument("task-123"); UnsavedRevision newRevision = document.getCurrentRevision().createRevision(); newRevision.setAttachment("photo.jpg", "image/jpeg", stream); }}
©2014 Couchbase Inc.
Attachments
66
protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { InputStream stream = getContentResolver().openInputStream(data.getData()); Document document = database.getDocument("task-123"); UnsavedRevision newRevision = document.getCurrentRevision().createRevision(); newRevision.setAttachment("photo.jpg", "image/jpeg", stream); newRevision.save(); }}
©2015 Couchbase Inc. ‹#›
©2015 Couchbase Inc. ‹#›
iOS branch: worhsop/start
Android branch: workshop/initial_state
Recommended