A simple NoSQL database(key-value pair) in Objective-C. It runs on iOS and OS X.
#NyaruDB
###\(・ω・\)SAN値!(/・ω・)/ピンチ!
這いよれ!ニャル子さんW
2013年4月7日(日)深夜1:05~からテレビ東京ほかにて放送スタート!
NyaruDB is a simple NoSQL database in Objective-C. It could be run on iOS and OS X.
It is a key-valu pair NoSQL database. You could search data by fields of the document.
##Feature
####More quickly than sqlite.
NyaruDB use memory cache, GCD and binary tree to optimize performance.
NoSQL with SQL:
NyaruDB: NSDictionary <-- NyaruDB --> File
sqlite: NSDictionary <-- converter --> SQL <-- sqlite3 function --> File
| NyaruDB | sqlite
:---------😐:---------😐:---------:
insert 1k documents | 11,000 ms
500 ms (async) | 36,500 ms
fetch 1k documents | 300 ms
50 ms (in cache) | 300 ms
search in 1k documents
for 10 times | 12 ms | 40 ms
(this test is on iPhone4)
NyaruDB use GCD to write/read documents, all accesses would be processed in a same dispatch.
Write: process with async GCD.
Read: process with sync GCD.
Writing documents to database will be processed in a async dispatch. So your code would not wait for writing documents. CPU will process the next command.
If next command is reading documents from database, the command will be processed after writing done.
####Clean query syntax.
// where type == 1 order by update
NSArray *documents = [[[collection where:@"type" equal:@1] orderBy:@"update"] fetch];
##Installation
####git
$ git clone git://github.com/kelp404/NyaruDB.git
####CocoadPods:
add Podfile
in your project path
platform :ios
pod 'NyaruDB'
$ pod install
##Management Tool
####NyaruDB Control
##Collection
Collection is like Table of sql database.
##Index
When you want to search data by a field, you should create a index.
If you want to search data by ‘email’, you should create a ‘email’ index before searching.
##Document
Document is data in the collection.
There is a member named key
in the document. Key is unique and datatype is NSString.
If the document has no key
when inserted, it will be automatically generated.
NSNull
, NSNumber
, NSDate
, NSString
, NSArray
, NSDictionary
NSString
, NSNumber
, NSDate
and NSNull
in the NSArray
)NSNull
, NSNumber
, NSDate
, NSString
##Access Database
###Instance
####iOS
[NyaruDB instance]
returns a static NyaruDB instance, and database path is /your-app/Documents/NyaruDB
.
NyaruDB *db = [NyaruDB instance];
####OS X
[[NyaruDB alloc] initWithPath:@"/tmp/NyaruDB"]
.
NyaruDB will scan all documents in collections when [NyaruDB init]
, so do not call init
too much.
In OS X, you should handle the static instance by yourself.
NyaruDB *db = [[NyaruDB alloc] initWithPath:@"/tmp/NyaruDB"];
###Create the collection
NyaruCollection *collectioin = [db collection:@"collectionName"];
###Create the index
NyaruCollection *collection = [db collection:@"collectionName"];
[collection createIndex:@"email"];
[collection createIndex:@"number"];
[collection createIndex:@"date"];
###Insert the document
If there is a document has the same ‘key’, it will be replace with the new document. (update document)
NyaruCollection *collection = [db collection:@"collectionName"];
NSDictionary *document = @{@"email": @"[email protected]",
@"name": @"Kelp",
@"phone": @"0123456789",
@"date": [NSDate date],
@"text": @"(」・ω・)」うー!(/・ω・)/にゃー!",
@"number": @100};
[collection put:document];
###Query
The field of the document which is key
or index
supports search.
key
supports equal
.
index
supports equal
, notEqual
, less
, lessEqual
, greater
, greaterEqual
and like
.
You could use and
(Intersection) or or
to append the query.
// search the document the 'key' is equal to 'IjkhMGIT752091136'
NyaruCollection *co = [db collection:@"collectionName"];
NSArray *documents = [[co where:@"key" equal:@"IjkhMGIT752091136"] fetch];
for (NSMutableDictionary *document in documents) {
NSLog(@"%@", document);
}
// search documents the 'date' is greater than now, and sort by date with DESC
NyaruCollection *co = [db collection:@"collectionName"];
NSDate *date = [NSDate date];
NSArray *documents = [[[co where:@"date" greater:date] orderByDESC:@"date"] fetch];
for (NSMutableDictionary *document in documents) {
NSLog(@"%@", document);
}
// search documents the 'date' is greater than now, and 'type' is equal to 2
// then sort by date with ASC
NyaruCollection *co = [db collection:@"collectionName"];
NSDate *date = [NSDate date];
NSArray *documents = [[[[co where:@"date" greater:date] and:@"type" equal:@2] orderBy:@"date"] fetch];
for (NSMutableDictionary *document in documents) {
NSLog(@"%@", document);
}
// search documents 'type' == 1 or 'type' == 3
NyaruCollection *co = [db collection:@"collectionName"];
NSArray *documents = [[[co where:@"type" equal:@1] or:@"type" equal:@3] fetch];
for (NSMutableDictionary *document in documents) {
NSLog(@"%@", document);
}
// count documents 'type' == 1
NyaruCollection *co = [db collection:@"collectionName"];
NSUInteger count = [[co where:@"type" equal:@1] count];
NSLog(@"%u", count);
###Delete documents
NyaruCollection *co = [db collection:@"collectionName"];
[co createIndex:@"number"];
[co put:@{@"number": @100}];
[co put:@{@"number": @200}];
[co put:@{@"number": @10}];
// remove by query
[[co where:@"number" equal:@10] remove];
// remove all
[[co all] remove];
###Sync & Async
put
and remove
will be run as async mode.
fetch
and count
will be run as sync mode. But all commands will be processed on a same dispatch.
After 1.4.1 NyaruDB has new messages about async fetch and count.
[NyaruQuery fetchAsync:(void (^)(NSArray *))handler]
[NyaruQuery countAsync:(void (^)(NSUInteger))handler]
If you wount to put documents as sync, you could use [NyaruCollection waitForWriting]
.
NyaruDB *db = [NyaruDB instance];
NyaruCollection *collection = [db collection:@"collection"];
NSDictionary *document = @{@"email": @"[email protected]",
@"name": @"Kelp",
@"phone": @"0123456789",
@"date": [NSDate date],
@"text": @"(」・ω・)」",
@"number": @100};
[collection put:document];
[collection waitForWriting]; // sync
// be Careful
NyaruDB *db = [NyaruDB instance];
NyaruCollection *collection = [db collection:@"collection"];
NSDictionary *document = @{@"email": @"[email protected]",
@"name": @"Kelp",
@"phone": @"0123456789",
@"date": [NSDate date],
@"text": @"(」・ω・)」",
@"number": @100};
for (NSUInteger index = 0; index < 1000; index++) {
// put 1k documents
[collection put:document];
}
// cpu will wait for documents write done.
// if this is main dispatch, it will be locked.
NSUInteger count = collection.count;
// you could try this
[collection countAsync:^(NSUInteger count) {
// this block run in main dispatch
}];
##Class
###NyaruDB interface
#pragma mark - Instance
/**
Get the shared instance for iOS.
@return NyaruDB shared instance
*/
+ (id)instance;
/**
Remove all database for iOS.
if you init database error, maybe need to call this message.
*/
+ (void)reset;
/**
Init NyaruDB for OS X.
@param path Database files are in this path.
@return NyaruDB instance
*/
- (id)initWithPath:(NSString *)path;
/**
Close all file handles and collections for OS X.
Before release instance you should invoke this method.
*/
- (void)close;
#pragma mark - Collection
- (NSArray *)collections;
- (NyaruCollection *)collection:(NSString *)name;
#pragma mark Remove
- (void)removeCollection:(NSString *)name;
- (void)removeAllCollections;
###NyaruCollection interface
#pragma mark - Index
- (NSArray *)allIndexes;
- (void)createIndex:(NSString *)indexName;
- (void)removeIndex:(NSString *)indexName;
- (void)removeAllindexes;
#pragma mark - Document
// put document
- (NSMutableDictionary *)put:(NSDictionary *)document;
// remove all documents (directly remove files)
- (void)removeAll;
// waiting for data writing
- (void)waitForWriting;
// clear cache
- (void)clearCache;
#pragma mark - Query
- (NyaruQuery *)all;
- (NyaruQuery *)where:(NSString *)indexName equal:(id)value;
- (NyaruQuery *)where:(NSString *)indexName notEqual:(id)value;
- (NyaruQuery *)where:(NSString *)indexName less:(id)value;
- (NyaruQuery *)where:(NSString *)indexName lessEqual:(id)value;
- (NyaruQuery *)where:(NSString *)indexName greater:(id)value;
- (NyaruQuery *)where:(NSString *)indexName greaterEqual:(id)value;
- (NyaruQuery *)where:(NSString *)indexName like:(NSString *)value;
#pragma mark - Count
- (NSUInteger)count;
- (void)countAsync:(void (^)(NSUInteger))handler;
###NyaruQuery interface
#pragma mark - Intersection
- (NyaruQuery *)and:(NSString *)indexName equal:(id)value;
- (NyaruQuery *)and:(NSString *)indexName notEqual:(id)value;
- (NyaruQuery *)and:(NSString *)indexName less:(id)value;
- (NyaruQuery *)and:(NSString *)indexName lessEqual:(id)value;
- (NyaruQuery *)and:(NSString *)indexName greater:(id)value;
- (NyaruQuery *)and:(NSString *)indexName greaterEqual:(id)value;
- (NyaruQuery *)and:(NSString *)indexName like:(NSString *)value;
#pragma mark - Union
- (NyaruQuery *)or:(NSString *)indexName equal:(id)value;
- (NyaruQuery *)or:(NSString *)indexName notEqual:(id)value;
- (NyaruQuery *)or:(NSString *)indexName less:(id)value;
- (NyaruQuery *)or:(NSString *)indexName lessEqual:(id)value;
- (NyaruQuery *)or:(NSString *)indexName greater:(id)value;
- (NyaruQuery *)or:(NSString *)indexName greaterEqual:(id)value;
- (NyaruQuery *)or:(NSString *)indexName like:(NSString *)value;
#pragma mark - Order By
- (NyaruQuery *)orderBy:(NSString *)indexName;
- (NyaruQuery *)orderByDESC:(NSString *)indexName;
#pragma mark - Count
- (NSUInteger)count;
- (void)countAsync:(void (^)(NSUInteger))handler;
#pragma mark - Fetch
- (NSArray *)fetch;
- (NSArray *)fetch:(NSUInteger)limit;
- (NSArray *)fetch:(NSUInteger)limit skip:(NSUInteger)skip;
- (NSMutableDictionary *)fetchFirst;
- (void)fetchAsync:(void (^)(NSArray *))handler;
- (void)fetch:(NSUInteger)limit async:(void (^)(NSArray *))handler;
- (void)fetch:(NSUInteger)limit skip:(NSUInteger)skip async:(void (^)(NSArray *))handler;
- (void)fetchFirstAsync:(void (^)(NSMutableDictionary *))handler;
#pragma mark - Remove
- (void)remove;
##Attention
equal
search##Thanks
##History
1.3
file header -> nyaruko
replace JSONKit with NyaruCollection.serialize()
1.2
file header -> (」・ω・)」うー!(/・ω・)/にゃー!1\n
optimize performance
new query syntax
1.1
file header -> (」・ω・)」うー!(/・ω・)/にゃー! \n