couchdb mobile

57
44 CouchDB mobile From Couch To 5k in 1 Hour Peter Friese / Stefan Reichert, Zü hlke Engineering

Upload: zuehlke

Post on 08-Jul-2015

6.913 views

Category:

Technology


1 download

DESCRIPTION

CouchDB mobile - From Couch to 5K in 1 Hour In this talk, I explain how to use CouchDB mobile to connect your iPhone with a a remote ChouchDB to build a RunKeeper clone. Synchronized access to data is an essential feature for many apps. CouchDB Mobile is a version of CouchDB that makes NoSQL approaches usable for mobile apps on Android and iOS. In this session, I will explain what CouchDB is, how it uses MapReduce and how CouchDB mobile can be used to build a runner's app similar to RunKeeper Live. Be prepared for a fun and entertaining session! Presentation held at MobileTech Connference in September 2012 at Frankfurt (Germany)

TRANSCRIPT

Page 1: CouchDB mobile

44

CouchDB mobileFrom Couch To 5k in 1 Hour

Peter Friese / Stefan Reichert, Zühlke Engineering

Page 2: CouchDB mobile

Integrating Twitter in Your iOS 5 Apps

@peterfriese

[email protected]/peter

http://peterfriese.de

Peter Friese

Page 3: CouchDB mobile

Integrating Twitter in Your iOS 5 Apps

Stefan Reichert

@stefanreichert

[email protected]

xing.to/stefanreichert

http://blog.wickedshell.net/

Page 4: CouchDB mobile

What we will cover today

1

2

3

What is CouchDB?

Serious amount of demos!

Couch25K - A Runner’s App

Page 5: CouchDB mobile

1

What is CouchDB?

Page 6: CouchDB mobile

CouchDB is...

A NoSQL Database.

CouchDB is...

A NoSQL Database.

Page 7: CouchDB mobile

CouchDB is...Document-Oriented.

Schema-Free.

{! "name": "Peter",! "company": "Zühlke Engineering",! "email": "[email protected]",! "languages": [! ! "Objective-C",! ! "Java",! ! "C#",! ! "JavaScript"! ]}

Page 8: CouchDB mobile

CouchDB is...

Schema-Free.

Erlang-Powered.

Put anything you like into your CouchDB. Really.

Page 9: CouchDB mobile

CouchDB is...

Erlang-Powered.

RESTful.

Page 10: CouchDB mobile

CouchDB is...RESTful.

Map/Reduce (JavaScript).

Fully embraces HTTP verbs

GETPUTPOSTDELETE

Page 11: CouchDB mobile

CouchDB uses...

Map/Reduce (JavaScript).

http

://re

sear

ch.g

oogl

e.co

m/a

rchi

ve/m

apre

duce

.htm

l

Page 12: CouchDB mobile

CouchDB uses...

Map/Reduce (JavaScript).

{"ip": "212.23.45.12","traffic": “18278", date: “2012-03-11”},{"ip": "74.12.345.1","traffic": “345", date: “2012-03-11”},{"ip": "212.23.45.12","traffic": “112244", date: “2012-03-12”},{"ip": "212.23.45.12","traffic": “8657", date: “2012-03-13”},{"ip": "74.12.345.12","traffic": “12", date: “2012-03-12”},{"ip": "10.122.111.22","traffic": “122222", date: “2012-03-11”}

Input

Page 13: CouchDB mobile

CouchDB uses...

Map/Reduce (JavaScript).

212.23.45.12 1827874.12.345.1 345212.23.45.12 112244212.23.45.12 865774.12.345.1 1210.122.111.22 122222

Mapper212.23.45.12 18278212.23.45.12 112244212.23.45.12 8657

74.12.345.1 1274.12.345.1 345

10.122.111.22 122222

Input for Reducer

Page 14: CouchDB mobile

CouchDB uses...

Map/Reduce (JavaScript).

212.23.45.12 18278212.23.45.12 112244212.23.45.12 8657

74.12.345.1 1274.12.345.1 345

10.122.111.22 122222

Input for Reducer212.23.45.12 139179

74.12.345.1 357

10.122.111.22 122222

After Reduce

Page 15: CouchDB mobile

CouchDB features...

Robust Replication.

Page 16: CouchDB mobile

CouchDB features...

Robust Replication.

Phone

Laptop

Server

Page 17: CouchDB mobile

2

Demos

Page 18: CouchDB mobile

Calling Home

curl localhost:5984

{"couchdb":"Welcome","version":"1.1.0"}

Page 19: CouchDB mobile

Creating a New DB

curl -X PUT localhost:5984/helloworld

{"ok":true}

Page 20: CouchDB mobile

Deleting a Database

curl -X DELETE http://localhost:5984/helloworld

{"ok":true}

Page 21: CouchDB mobile

Creating a New Documentcurl -X POST -H "Content-Type: application/json" localhost:5984/helloworld -d @peter.json

{"ok":true,"id":"f8e42aaa4bc77124c286be13f000054e","rev":"1-4dc37117e0da26d9c50dc92d4cbb04cc"}

Page 22: CouchDB mobile

Curious? GET Your Document!curl http://localhost:5984/helloworld/f8e42aaa4bc77124c286be13f000054e

{ "_id": "f8e42aaa4bc77124c286be13f000054e", "_rev": "1-4dc37117e0da26d9c50dc92d4cbb04cc", "name": "Peter", "company": "Zühlke Engineering", "email": "[email protected]"}

Page 23: CouchDB mobile

Anatomy of a Document{ "_id": "f8e42aaa4bc77124c286be13f000054e", "_rev": "1-4dc37117e0da26d9c50dc92d4cbb04cc", "name": "Peter", "company": "Zühlke Engineering", "email": "[email protected]"}

UUID - very unique identifier

Page 25: CouchDB mobile

Welcome to Futon!

Admin interface for CouchDBCRUD for DocumentsManage ViewsManage Replication

Page 26: CouchDB mobile

3

Couch25K - A Runner’s App

Page 27: CouchDB mobile

Basic Idea

Phone IrisCouch

2-way 2-way

Phone

Page 28: CouchDB mobile

CouchDB Mobile

on your Ph

one?

Page 29: CouchDB mobile

CouchDB Mobile

CouchDB

Your app CouchCocoa lib Your app

CouchDB

Ektorp lib

Page 30: CouchDB mobile

CouchDB Mobile

SQlite

Your app CouchCocoa lib

SQlite

TouchDB lib

Your appEktorp lib

TouchDB lib

Page 31: CouchDB mobile

CouchDB Mobile

“TouchDB is a lightweight CouchDB-compatible database engine suitable for embedding into mobile or desktop apps. Think of it this way: If CouchDB is MySQL, then TouchDB is SQLite.” - Jens Alfke, Couchbase

Labs

Page 32: CouchDB mobile

Start a Local CouchCouchTouchDBServer *server =[CouchTouchDBServer sharedInstance];

NSAssert(!server.error, @"Error initializing TouchDB server: %@", server.error);

self.database = [serverdatabaseNamed:@"couch25k"];

NSError *error;if (! [self.database ensureCreated:&error]) {// raise errorself.connected = false;

}

Page 33: CouchDB mobile

Start a Local Couchtry {TDServer touchDBServer = new TDServer(filesDir);

!HttpClient httpClient = newTouchDBHttpClient(touchDBServer);

CouchDbInstance couchDBInstance = new StdCouchDbInstance(httpClient);

!CouchDbConnector couchDBConnector =couchDBInstance.createConnector(COUCH25K_DB,true);

! ...} catch (IOException e) {! Log.e(TAG, "Error starting TDServer", e);}

Page 34: CouchDB mobile

Trackpoints

{ "run": "run-peterfriese-19", "user": "peterfriese", "lon": "9.990512659959458", "time": "2012-03-24 07:39:27 +0000", "lat": "53.73176022303823"}

Page 35: CouchDB mobile

Saving a TrackpointNSDictionary *trackpointProperties = [NSDictionary dictionaryWithObjectsAndKeys: (...)

CouchDocument *trackpointDocument =[database untitledDocument];

RESTOperation* op = [trackpointDocument putProperties:trackpointProperties];

[op onCompletion: ^{if (op.error)NSLog(@"Couldn't save the new item");

}];[op start];

Page 36: CouchDB mobile

Saving a Trackpoint

public class TrackPoint extends CouchDbDocumentEktorp: JPA for CouchDB

Repository Supportpublic class TrackPointRepository extends ! CouchDbRepositorySupport<TrackPoint>

... so saving a TrackPoint is pretty easytrackPointRepository.add(trackPoint);

Page 37: CouchDB mobile

Sync with the Server

NSURL *url = [NSURL URLWithString:@"http://peterfriese.iriscouch.com/couch25k"];

[self.database replicateWithURL:url exclusively: YES];

Page 38: CouchDB mobile

Sync with the Server

ReplicationCommand commandPull = newReplicationCommand.Builder().source(COUCH25K_REMOTE_DB).target(COUCH25K_DB).continuous(true).build();

try {couchDBInstance.replicate(commandPull);

} catch (Exception exception) {Log.e(TAG, exception.getMessage(), exception);

}

Pull from Server

Page 39: CouchDB mobile

Sync with the Server

ReplicationCommand commandPush = newReplicationCommand.Builder().source(COUCH25K_DB).target(COUCH25K_REMOTE_DB).continuous(true).build();

try {couchDBInstance.replicate(commandPush);

} catch (Exception exception) {Log.e(TAG, exception.getMessage(), exception);

}

Push to Server

Page 40: CouchDB mobile

Demo

Page 41: CouchDB mobile

Display List of Runs (JavaScript)

function(doc) { emit(doc.run, 1);}

Map

run-1 1run-1 1run-1 1run-2 1run-2 1

function(keys, values) { return sum(values);}

Reduce

run-1 3run-2 2

Page 42: CouchDB mobile

Display List of Runs (Obj-C)

[design defineViewNamed: @"runs" mapBlock: MAPBLOCK({id run = [doc objectForKey:@"run"];if (run) emit(run, nil);

})

reduceBlock:REDUCEBLOCK({return [NSNumber numberWithInt:values.count];

})

Map

Reduce

Page 43: CouchDB mobile

Display List of Runs (Java)

new TDViewMapBlock() {public void map(Map<String, Object> doc, TDViewMapEmitBlock emitter) {if (doc.containsKey("run")) {emitter.emit(doc.get("run"), doc.get("_id"));

}}

}

Map

Page 44: CouchDB mobile

Display List of Runs (Java)

new TDViewReduceBlock() {public Object reduce(List<Object> keys, List<Object>values, boolean rereduce) {if (rereduce) {int sum = 0;for (Object object : values) {sum += (Integer) object;

}return sum;

}return values.size();

}};

(Re-) reduce

Page 45: CouchDB mobile

Filtering

Phone IrisCouch

sync 2-way

Phone 2

sync 2-way

Filter by name

Peter Stefan

Page 46: CouchDB mobile

Filtering

by_user:

function(doc, rq) { if(doc.user == rq.query.username) { return true;

} return false;

}

CouchDB

Page 47: CouchDB mobile

FilteringNSArray *replications = [self.database replicateWithURL:url exclusively: YES];

CouchPersistentReplication *from = [replications objectAtIndex:0];

from.continuous = YES;

from.filter = @"couch25k/by_user";NSDictionary *filterParams = [NSDictionary dictionaryWithObjectsAndKeys:@"peterfriese", @"username", nil];

from.query_params = filterParams;

Page 48: CouchDB mobile

FilteringMap<String, Object> queryParams =new HashMap<String, Object>();

queryParams.put("username", "stefanreichert");

ReplicationCommand commandPull = newReplicationCommand.Builder().source(COUCH25K_REMOTE_DB).target(COUCH25K_DB).continuous(true).filter("by_user").queryParams(queryParams).build();

try {! couchDBInstance.replicate(commandPull);} catch (Exception e) {! Log.e(TAG, exception.getMessage(), e);}

Page 49: CouchDB mobile

Maps, please!

Page 50: CouchDB mobile

Query Trackpoints by Run

mapBlock: MAPBLOCK({NSString *run = (NSString *)[doc objectForKey:@"run"];id time = [doc objectForKey:@"time"];NSMutableArray *key = [[NSMutableArray alloc] init];[key addObject:run];[key addObject:time];emit(key, doc);})

Map

[run-peter-1, 2012-03-23 10:10] {lat:..., lon:...}[run-peter-1, 2012-03-23 10:11] {lat:..., lon:...}[run-peter-2, 2012-03-26 20:05] {lat:..., lon:...}[run-peter-2, 2012-03-26 20:06] {lat:..., lon:...}[run-peter-2, 2012-03-26 10:07] {lat:..., lon:...}

Page 51: CouchDB mobile

Query Trackpoints by Run

CouchQuery *query = [[self.database designDocumentWithName: @"couch25k"] queryViewNamed: @"waypoints_by_run"];

CouchLiveQuery *livequery = [query asLiveQuery];

[livequery setStartKey:[NSArray arrayWithObjects:self.runKey, nil]];

[query setEndKey:[NSArray arrayWithObjects:self.runKey, @"ZZZ", nil]];

Query

Page 52: CouchDB mobile

Query Trackpoints by Run

new TDViewMapBlock() {public void map(Map<String, Object> document,TDViewMapEmitBlock emitter) {if (document.containsKey("run")) {document.get("run"), document.get("_id"));

}}

Map

Page 53: CouchDB mobile

Query Trackpoints by RunQueryViewQuery viewQuery = newViewQuery().designDocId("_design/TrackPoint").viewName("trackpoint_by_run").key(runId);

ViewResult result = db.queryView(viewQuery);List<TrackPoint> trackPoints = new ArrayList<TrackPoint>();

for (Row row : result.getRows()) {TrackPoint trackPoint = get(row.getValue());trackPoints.add(trackPoint);

}return trackPoints;

Page 54: CouchDB mobile

And finally...

http://josephta.me/about-joseph-tame/

Page 55: CouchDB mobile

... a Tribute to Steve Jobs GPX courtesy

of Joseph Tame - Thanks!

http://bit.ly/HbDRod

Page 56: CouchDB mobile

44

Relax!

Page 57: CouchDB mobile

Thanks!Peter FriesePrincipal Consultant

Zühlke Engineering GmbHAm Sandtorkai 6620457 Hamburg

+49 151 108 604 72Available for consulting,discussing all things mobile and frosty beverages

Stefan Reichert

Senior Software Engineer

Zühlke Engineering GmbH

Am Sandtorkai 66

20457 Hamburg

+49 173 961 43 36

@stefanreichert @peterfriese

PS: we’re hiring...