CouchDB mobile

Post on 08-Jul-2015

6906 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

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

44

CouchDB mobileFrom Couch To 5k in 1 Hour

Peter Friese / Stefan Reichert, Zühlke Engineering

Integrating Twitter in Your iOS 5 Apps

@peterfriese

peter.friese@zuehlke.comxing.to/peter

http://peterfriese.de

Peter Friese

Integrating Twitter in Your iOS 5 Apps

Stefan Reichert

@stefanreichert

stefan.reichert@zuehlke.com

xing.to/stefanreichert

http://blog.wickedshell.net/

What we will cover today

1

2

3

What is CouchDB?

Serious amount of demos!

Couch25K - A Runner’s App

1

What is CouchDB?

CouchDB is...

A NoSQL Database.

CouchDB is...

A NoSQL Database.

CouchDB is...Document-Oriented.

Schema-Free.

{! "name": "Peter",! "company": "Zühlke Engineering",! "email": "peter.friese@zuehlke.com",! "languages": [! ! "Objective-C",! ! "Java",! ! "C#",! ! "JavaScript"! ]}

CouchDB is...

Schema-Free.

Erlang-Powered.

Put anything you like into your CouchDB. Really.

CouchDB is...

Erlang-Powered.

RESTful.

CouchDB is...RESTful.

Map/Reduce (JavaScript).

Fully embraces HTTP verbs

GETPUTPOSTDELETE

CouchDB uses...

Map/Reduce (JavaScript).

http

://re

sear

ch.g

oogl

e.co

m/a

rchi

ve/m

apre

duce

.htm

l

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

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

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

CouchDB features...

Robust Replication.

CouchDB features...

Robust Replication.

Phone

Laptop

Server

2

Demos

Calling Home

curl localhost:5984

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

Creating a New DB

curl -X PUT localhost:5984/helloworld

{"ok":true}

Deleting a Database

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

{"ok":true}

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

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

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

{ "_id": "f8e42aaa4bc77124c286be13f000054e", "_rev": "1-4dc37117e0da26d9c50dc92d4cbb04cc", "name": "Peter", "company": "Zühlke Engineering", "email": "peter.friese@zuehlke.com"}

Anatomy of a Document{ "_id": "f8e42aaa4bc77124c286be13f000054e", "_rev": "1-4dc37117e0da26d9c50dc92d4cbb04cc", "name": "Peter", "company": "Zühlke Engineering", "email": "peter.friese@zuehlke.com"}

UUID - very unique identifier

Welcome to Futon!

Admin interface for CouchDBCRUD for DocumentsManage ViewsManage Replication

3

Couch25K - A Runner’s App

Basic Idea

Phone IrisCouch

2-way 2-way

Phone

CouchDB Mobile

on your Ph

one?

CouchDB Mobile

CouchDB

Your app CouchCocoa lib Your app

CouchDB

Ektorp lib

CouchDB Mobile

SQlite

Your app CouchCocoa lib

SQlite

TouchDB lib

Your appEktorp lib

TouchDB lib

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

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;

}

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);}

Trackpoints

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

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];

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);

Sync with the Server

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

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

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

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

Demo

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

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

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

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

Filtering

Phone IrisCouch

sync 2-way

Phone 2

sync 2-way

Filter by name

Peter Stefan

Filtering

by_user:

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

} return false;

}

CouchDB

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;

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);}

Maps, please!

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:...}

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

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

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;

And finally...

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

... a Tribute to Steve Jobs GPX courtesy

of Joseph Tame - Thanks!

http://bit.ly/HbDRod

44

Relax!

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...

top related