couchbase talk
TRANSCRIPT
Writing Mobile Applications with
CouchbaseKnoxville Cocoaheads
March 2016
Who is this guy?• Mike Hagedorn
• Language Polyglot
Why Couchbase?
Changing face of IT DemandsHAScalableAgile, Schemaless
CB: Synching, Admin GUI, SDKs
Couchbase History
Couchbase Terms• Node
• Cluster
• Bucket
• Document
• View
Couchbase Components
Mobile embedded local db with syncGw internet facing componentServer: Ent grade nosql db
Couchbase Server
Couchbase LiteCouchbase Lite is an embedded JSON database that can work standalone, in a P2P network, or as a remote endpoint for Couchbase Server.
EmbeddedAll IO is localSyncs are transparent in backgroundDisconnected operationNO PUSHNO Network
CBL
Device 1
CBL
Device 2
CB Server
Cluster 1with GW!
Sync Gateway
CBL
Device 1
CBL
Device 2
CB Server
Cluster 1
Data Needed Here!
?
Remote Data Center
SGW
Couchbase Model
• An object oriented wrapper on top of CBLDocument
• Somewhat like NSManagedObject
Couchbase Challenges
• Complicated Queries are Hard
• Views!
Getting Started
• DL Couchbase Lite Framework
• Add CouchbaseLite.framework to your project
• There is no step 3
Initialization
//AppDelegate CBLManager *manager = [CBLManager sharedInstance]; NSError *error; self.database = [manager databaseNamed:kDBName error: &error]; if (error) { NSLog(@"error getting database %@",error);
exit(-1); }
DatabaseRockets
Name Weight Diameter Cd
alpha 29 25 0.75
hawk 35 30 0.8
Document
{ "coefficientFriction": 0.75, "diameter": 25, "name": "alpha110", "type": "rocket", "weight": 23 }
# Bb6YvfoCH7NIgsVDtgjE7O
Unique IDMay contain binary attachments
Database View
//RootController or CBModel //Define a view that only returns documents of type ‘kRocketDocType’ CBLView* view = [db viewNamed: @"rockets"];
if (!view.mapBlock) { // Register the map function, the first time we access the view: [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString:kRocketDocType]) emit(doc[@"name"], nil); }) reduceBlock: nil version: @"1"]; }
Map/ReduceCalled on every documentOptional Reduce
Using Views in your UI
// Create a query showing rockets: CBLLiveQuery* query = [[[database viewNamed:@"rockets"] query] asLiveQuery];
// Plug the query into the CBLUITableSource, which will use it to drive the table.
// (The CBLUITableSource uses KVO to observe the query's .rows
self.dataSource.query = query;self.dataSource.labelProperty = @"name";
// Assumes something like this in your controller
@property (nonatomic) IBOutlet UITableView* tableView;
@property (nonatomic) IBOutlet CBLUITableSource* dataSource;
Customizing Table Cells- (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 }
Selecting A Row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"didSelectRowAtIndexPath"); NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row]; ASDRocket* rocket = [ASDRocket modelForDocument: row.document];
// Do something with rocket… }
Adding Items- (IBAction) insertNewObject: (id)sender {
ASDRocket* rocket = [ASDRocket modelForNewDocumentInDatabase:self.database];
rocket.name=name; rocket.weight = 23.0; NSError* error; if (![rocket save: &error]) { return nil; } NSLog(@"Rocket Created");
}
Deleting Items-(void) tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ if (editingStyle == UITableViewCellEditingStyleDelete){ CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row]; ASDRocket* rocket = [ASDRocket modelForDocument: row.document]; NSError* error; if (![rocket deleteDocument: &error]){ NSLog(@"Unable to delete Rocket"); return; } [self.tableView reloadData]; }
}
Replications CBLReplication *pull; CBLReplication *push; h; pull = [_database createPullReplication:_remoteURL]; pull.continuous = YES; pull.network = @"WiFi";
push = [_database createPushReplication:_remoteURL]; push.continuous = YES; pull.network = @"WiFi";
[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(replicationProgress:) name:kCBLReplicationChangeNotification push];
[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(replicationProgress:) name:kCBLReplicationChangeNotification pull];
CBLModel• Maps Objects to documents
@interface ASDRocket : CBLModel
+ (NSString*) docType;
@property (strong) NSString *name; @property (assign) double diameter; @property (assign) double weight; @property (assign) double coefficientFriction;
/** Returns a query for all the rockets in a database. */ + (CBLQuery*) queryRocketsInDatabase: (CBLDatabase*)db;
/** Returns a query for all the rockets with name in a database */ + (CBLQuery*) findInDatabase:(CBLDatabase*)db byName:(NSString *)name;
@end
CBLModel• No types in documents
• convention is to use type field
• Map functions can pick out docs with the right type
if (doc.type == “rocket”){
emit(doc.created, doc.text)
};
Demo
• https://github.com/mwhagedorn/couchbase_ios_rockettown
• https://github.com/mwhagedorn/couchbase_osx_rockettown
• Two platforms synching to one database
Questions?
• @mwhagedorn