Мобильный NoSQL - 2015.mobius-piter.ruStorage: SQLite / ForestDB • ForestDB is a new...
Transcript of Мобильный NoSQL - 2015.mobius-piter.ruStorage: SQLite / ForestDB • ForestDB is a new...
Никифоров Данил
#couchbase #couchbaselite #ios
Мобильный NoSQL и синхронизация
• Немного теории
• Couchbase Lite / CRUD
• Включение синхронизации
• Demo / CRM
• Q&A
Как мы обычно храним данные в iOS?
‣ CoreData (ORM on top of SQLite,…)
‣ SQLite through FMDB
‣ NSUserDefaults (KV)
‣ iCloud / CloudKit (syncable)
‣ …hand-made something
‣ Couchbase Lite
SQLite
FMDB
Core Data
Couchbase Lite это легковесный Framework реализующий документ-ориентированное и синхронизируемое хранилище для мобильных устройств и встраиваемых систем.
What is Couchbase Lite?
6.0+ 2.3+
Легковесность:• Является библиотекой подключаемой к приложению, а не дополнительным серверным процессом.
• Быстрый запуск на относительно медленных CPU: <50ms на свежих iPhone.
• Не высокое потребление памяти и хорошая производительность.
Документо-ориентированность• Данные храниться ввиде JSON документов.
• Отсутствует схема базы данных
• Данные могут эволюционировать без необходимости явных миграций
• Документы могут содержать сравнительно большие вложения(attachments)
• Map/reduce indexing позволяет искать объекты без необходимости использовать особый язык запросов.
• Документы могут содержать тексты и географические координаты которые эффективно индексируются для full-text search или geo-querying
Синхронизируемость• Любые 2 копии базы могут быть синхронизированы используя эффективный и надежный REST-based протокол. (eventually consistent)
• Решаются вопросы нестабильного соединения.
• Конфликты синхронизации могут быть найдены и разрешены основываясь на логике приложения
• Поддержка on-demand и continuous синхронизации
Storage: SQLite / ForestDB• ForestDB is a new storage engine (based on Hierarchical B+-Trees)
which can be used in CBL. It has some benefits in speed (2x-5x) and RAM (lower) footprint.
• ForestDB has also some drawbacks/issues:
• Still in Beta: available in master branch (needs manual building of ForestDB library).
• No easy way to switch storage on the go
• FullText search is very limited and slower than FTS3 (SQLite)
• GEO Search is very limited (only point containment)
https://github.com/couchbase/couchbase-lite-ios/wiki/ForestDB
Быстрый Старт• Скачать и добавить Framework:
http://www.couchbase.com/mobile или из GitHub
• #import <CouchbaseLite/CouchbaseLite.h>
• можем уже записать документ в базу
Быстрый Старт• pod 'couchbase-lite-ios', ‘~> 1.0.3'
• pod install
• #import <CouchbaseLite/CouchbaseLite.h>
• можем уже записать документ в базу
CBLDatabase * database = [manager databaseNamed:@"db-name" error: &error];
NSDictionary * dictionary = @{@"first_name": @"Danil", @"last_name" : @"Nikiforov", @"timestamp" : @"2014-04-30T17:15"};
CBLDocument * document = [database createDocument];
CBLRevision * revision = [document putProperties: dictionary error: &error];
CBLDocument *retrievedDoc = [database documentWithID: docID];
CBLManager * manager = [[CBLManager alloc]init];
NSString * docID = document.documentID;
[retrievedDoc deleteDocument:&error];
{ "_id" : "369A75CE-9C35-4B15-B127-51D2B96D1F5B", "_rev": “1-54b1d651b3d0003c77807314a223baa5", "first_name":"Danil", "last_name" :"Nikiforov", "timestamp" :”2014-04-30T17:15" }
CRUD
CRUD
CBLDocument *doc = [database documentWithID: docID];
[doc update:^BOOL(CBLUnsavedRevision * rev) { /* can be called multiple times */ rev[@"status"] = status;
return YES; } error:&err];
Revision History
• При каждом изменении документа создается новая ревизия (CBLRevision)
• Удаление это создание ревизии с полем “_deleted”
• Нам возможно потребуется устранять конфликты
• [database compact];
Local Documents
_local/<your-id>
Models
@interface Person : CBLModel
@property (strong) NSString * firstName; @property (strong) NSString * lastName; @property (strong) NSDate * timestamp; @property (strong) NSArray * children;
@property (strong) Company * company;
-(UIImage*) photo;
@end
@implementation Person
@dynamic firstName, lastName, timestamp, company, children;
...
@end
person.firstName = @"Andrew"; person.lastName = @"Tokarev"; person.timestamp = [NSDate date]; person.children = @[@"Max"]; person.company = al_digit;
NSError * error = nil;
Person * person = [[Person alloc] initWithNewDocumentInDatabase:database];
[person save:&error];if (error) { /* to handle errors properly */ }
{ “_id" : "B6A59791-7B2D-4402-9F53-7CB146B2CE98", "_rev": "1-f7c04cea9c877ea8692cb86a4a93cebe", "firstName":"Andrew", “lastName" :"Tokarev", "timestamp":"2014-04-29T17:51:49.538Z", "children":["Max"], “company" :"DCD6F62A-B0FA-4D46-9874-03B9BF47D37F"}...
CBLDocument * existing_document = ...;
person = [Contact modelForDocument:existing_document];
[person deleteDocument:&error];
CRUD
Attachments- (void) setPhoto:(UIImage*)photo { NSData * photoData = UIImagePNGRepresentation(photo); [self setAttachmentNamed:@"photo" withContentType:@"image/png" content:photoData];}
- (UIImage*)photo{ NSData * photoData = [[self attachmentNamed:@"photo"] content]; return [UIImage imageWithData:photoData];}
- (void) removePhoto{ [self removeAttachmentNamed:@"photo"]; }
Map / Reduce
How to Search?
Map / Reduce
_id: apple-1 _id: orange-cat_id: apple-2
Map / Reduce
_id: apple-1 _id: apple-2 _id: orange-cat
key value doc-id
Red Apple nil apple-1
Green Apple nil apple-2
Indexingid type name
apple-1 apple Red Apple
pa-1 pineapple Thai Pineapple
apple-2 apple Green Apple
orange-cat orange Kitty
xxx … …
key value doc_id
Red Apple nil apple-1
Green Apple nil apple-2
… … …
View / QueryCBLView * view = [database viewNamed:@"fruits/Apples"];
CBLQuery * query = [view createQuery];query.descending = YES; query.limit = 10;
for (CBLQueryRow *row in [query run:&error]) {...}
emit (doc[@"name"], nil); }
if ([doc[@“type"] isEqualToString:@"apple"]) {
[view setMapBlock:^(NSDictionary *doc, CBLMapEmitBlock emit) {
} version:@"1"];
All Documents QueryCBLQuery* query = [database createAllDocsQuery]; query.allDocsMode = kCBLOnlyConflicts;
CBLQueryEnumerator* result = [query run: &error]; for (CBLQueryRow* row in result) { // do work }
Persons for Company- (CBLQuery *)queryPersonsForCompany:(Company *)comapny{
}
CBLView * view = [self.database viewNamed: @"personsForCompany"]; if(![view mapBlock]) { [view setMapBlock:^(NSDictionary *doc, CBLMapEmitBlock emit){
} version:@"1"]; }
NSString * companyId = comapny.companyId; CBLQuery * query = [view createQuery]; query.keys = @[companyId]; return query;
NSString * companyId = doc[@"company"]; if (companyId) { emit (companyId, nil); }
Synchronization
CBLReplication * push = [database createPushReplication:syncGatewayUrl];CBLReplication * pull = [database createPullReplication:syncGatewayUrl];
for (CBLReplication * repl in @[push, pull]) { [repl setContinuous:YES]; } [repl start];
CBLReplication * push = [database createPushReplication:syncGatewayUrl];CBLReplication * pull = [database createPullReplication:syncGatewayUrl];
for (CBLReplication * repl in @[push, pull]) { [repl setContinuous:YES];
} [repl start];
[repl setAuthenticator:[self createFacebookAuthenticator]];
Authentication
- (void) createFacebookAuthenticator { return [CBLAuthenticator facebookAuthenticatorWithToken:@"access token"]; }
Sync Gateway
Sync Functionfunction(doc, oldDoc) { /* we can route doc to channel(s) */ channel(“all_docs”);
/* we can create role, by assigning users to it */ role(userID, "role:admin");
/* we can require user/role/channel to proceed */ requireUser(userID); requireRole(role); requireAccess(channel); /* throw some exception */ throw ({forbidden: "error message"})
/* we can grant user/role access to channel(s) */ access(userID, “all_docs”); access("role:admin", "all_docs"); /* we log something to console*/ log(“some text") }
Channels
document_1
document_2
Channel A
Channel B
document_2
document_1
document_3
Edward
Janedocument_3
document_3
document_2
Replication Conflicts1-abcd 2-abce
1-abcd 2-abce 3-feed 1-abcd 2-abce 3-food
1-abcd 2-abce
3-feed
3-food
4-good
4-dead
Doc: Native-API / Document / Conflicts
DemoCouchbase CRM
‣ Документация:
‣ http://docs.couchbase.com/couchbase-lite
‣ Couchbase Mobile Google Group:
‣ https://groups.google.com/forum/#!forum/mobile-couchbase
#couchbase #couchbaselite #ios
Q&A
Thank you
#couchbase #couchbaselite #ios