Mobile workshop: Couchbase lite in-depth
Mobile workshop: Couchbase lite in-depth from Couchbase
Published in: Technology
Transcript
- 1. COUCHBASE LITE IN-‐DEPTH James Nocentini, Developer Advocate, Couchbase
- 2. ©2014 Couchbase Inc. This morning ▪ Using Documents and Revisions ▪ Utilising convenience Data Model APIs ▪ Creating Couchbase Lite Views ▪ Querying Views ▪ Live Queries 2
- 3. ToDo Lite
- 4. ©2014 Couchbase Inc. 4
- 5. Demo
- 6. ©2014 Couchbase Inc. Data Model 6
- 7. ©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
- 8. 1. Database
- 9. ©2014 Couchbase Inc. 9©2015&Couchbase&Inc. Initialization DemoAppDelegate.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
- 10. ©2014 Couchbase Inc. Database 10 public class Application extends android.app.Application { @Override public void onCreate() { super.onCreate(); } }
- 11. ©2014 Couchbase Inc. Database 11 public class Application extends android.app.Application { @Override public void onCreate() { super.onCreate(); Manager manager = new Manager(new AndroidContext(getApplicationContext()), Manager.DEFAULT_OPTIONS); } }
- 12. ©2014 Couchbase Inc. Database 12 public class Application extends android.app.Application { @Override public void onCreate() { super.onCreate(); Manager manager = new Manager(new AndroidContext(getApplicationContext()), Manager.DEFAULT_OPTIONS); Database database = manager.getDatabase("dbname"); } }
- 13. ©2014 Couchbase Inc. 13©2015&Couchbase&Inc. Manager ▪ TopJlevel&object,&usually&a&singleton& ▪ A&collection&of&named&databases& ▪ Locates&databases&in&filesystem 19
- 14. ©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
- 15. ©2014 Couchbase Inc. Database 15
- 16. ©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
- 17. ©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>());
- 18. ©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();
- 19. ©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);
- 20. ©2014 Couchbase Inc. Documents 20 Document document = database.getDocument("task-123");
- 21. ©2014 Couchbase Inc. Documents 21 Document document = database.getDocument("task-123"); String title = document.getProperty("title");
- 22. ©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");
- 23. ©2014 Couchbase Inc. Documents { "_id": "123", "type": "list", "title": "Today’s list", "owner": "1234567890", "members": [ "0987654321", "0192837465" ] } 23
- 24. Models
- 25. ©2014 Couchbase Inc. Models 25 @interface Task : CBLModel @end @implementation Task @end
- 26. ©2014 Couchbase Inc. Models 26 @interface Task : CBLModel @property NSString *title; @end @implementation Task @dynamic title; @end
- 27. ©2014 Couchbase Inc. Models 27 @interface Task : CBLModel @property NSString *title; @property bool checked; @end @implementation Task @dynamic title, checked; @end
- 28. ©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
- 29. ©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];
- 30. ©2015 Couchbase Inc. ‹#›
- 31. ©2014 Couchbase Inc. 31 2.+Views+&+Queries
- 32. ©2014 Couchbase Inc. 32©2015&Couchbase&Inc. Creating+A+Database+View RootViewController.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
- 33. ©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
- 34. ©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 alldocuments map function View+ “byDate” 27
- 35. ©2014 Couchbase Inc. 35©2015&Couchbase&Inc. Creating+A+Database+View RootViewController.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
- 36. ©2014 Couchbase Inc. 36©2015&Couchbase&Inc. Driving+the+Table+from+a+View+Query RootViewController.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
- 37. ©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 QueryRow QueryRow QueryRow .limit&=&3& .offset&=&…& .reverse&=&…& .startKey&=&…& .endKey&=&…
- 38. ©2014 Couchbase Inc. 38©2015&Couchbase&Inc. LiveQuery+Driving+A+GUI+Table 31 LiveQuery Query CBLUITableN Source UITableView Your+ Controller data source delegate Note:&CBLUITableSource&is&iOSJonly
- 39. ©2014 Couchbase Inc. 39©2015&Couchbase&Inc. LiveQuery+Driving+A+GUI+Table 32
- 40. ©2014 Couchbase Inc. 40©2015&Couchbase&Inc. Driving+the+Table+from+a+View+Query RootViewController.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
- 41. ©2014 Couchbase Inc. 41©2015&Couchbase&Inc. Displaying+Table+Cells DemoAppDelegate.m:131 W!(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 theCBLUITableSourcewhen it’s told todisplay a cell.
- 42. ©2014 Couchbase Inc. 42©2015&Couchbase&Inc. Responding+To+Taps DemoAppDelegate.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 theUITableView itself
- 43. ©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 Controller Model& (Database) GUI&View User&event Update&doc DocumentChangedRedraw 36
- 44. Index
- 45. ©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
- 46. ©2014 Couchbase Inc. Map/Reduce Index 46 + (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { }
- 47. ©2014 Couchbase Inc. Map/Reduce Index 47 + (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { CBLView* view = [db viewNamed: @"lists"]; if (!view.mapBlock) { } return [view createQuery]; }
- 48. ©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]; }
- 49. ©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]; }
- 50. ©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; }
- 51. ©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; }
- 52. ©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; }
- 53. ©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; }
- 54. ©2015 Couchbase Inc. ‹#›
- 55. Query
- 56. ©2014 Couchbase Inc. Query 56 Query query = database.getView("tasksByDate").createQuery(); QueryEnumerator result = query.run(); for (Iterator<QueryRow> it = result; it.hasNext(); ) { // do something }
- 57. ©2014 Couchbase Inc. Query 57 LiveQuery liveQuery = database.getView("tasksByDate").createQuery().toLiveQuery();
- 58. ©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 } });
- 59. ©2014 Couchbase Inc. Query 59
- 60. ©2015 Couchbase Inc. ‹#›
- 61. Attachments
- 62. ©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()); } }
- 63. ©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"); } }
- 64. ©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(); } }
- 65. ©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); } }
- 66. ©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(); } }
- 67. ©2015 Couchbase Inc. ‹#›
- 68. ©2015 Couchbase Inc. ‹#›
- 69. ©2015 Couchbase Inc. ‹#› http://bit.ly/1KKiA8g
- 70. ©2015 Couchbase Inc. ‹#› http://bit.ly/1FrUJn0
- 71. iOS branch: worhsop/start Android branch: workshop/initial_state
No comments:
Post a Comment