Search code examples
iosdatabasekey-value-storeyapdatabase

key value store database on iOS


One example of an effort to create a key value store database on the iOS is YapDatabase.

However, I have no experience with it, and would like to understand whether it's worth it to use this, instead of something like Core Data or FMDB.

One critical question I have is: How do I manage object relationships with this database?

If I can avoid object relationships, I'm looking for suggestion or database design tips on how to solve the problem of an object that has many-to-many relationship to another object.

Let's consider one use case (this is just an example, to help solving this problem):

sender <<->> message <<->> recipient

sender has a: 
    photo_data, 
    name, 
    gender, 
    age, 
    email, 
    username, 
    twitter_id, 
    facebook_id, 
    sender_id

recipient has a: 
    photo_data, 
    name, 
    gender, 
    age, 
    email, 
    username, 
    twitter_id, 
    facebook_id, 
    recipient_id

message has a:
    text, 
    rich_text, 
    picture_data, 
    voice_data, 
    shared_url, 
    message_id

I have thought about using the message_id, sender_id, and recipient_id to relate each model, but is there a better way?


Solution

  • I've done something like this, which may not be an exact fit, but may help.

    I had a similar setup for a chat application. Every message had a sender and recipient, but obviously the current user was one of the two. So I stored all the messages in their own collection, where the name of the collection was the id of the non-current-user.

    If using YapDatabase, you'd use the YapCollectionsDatabase class.

    == Edit ==

    You'd start by making your message & user class:

    @interface Message : NSObject <NSCoding> ...
    
    @property (...) NSString *sender_id;
    @property (...) NSString *recipient_id;
    @property (...) NSString *user_id; // sender_id || recipient_id (non-current-user)
    
    @property (...) NSDate *timestamp;
    ...
    @end
    
    @interface User : NSObject <NSCoding>
    
    @property (...) NSString *user_id;
    ...
    @end
    

    Now to store these objects in the database.

    We start with YapCollectionsDatabase. This is a collection/key/value store. So when a new message arrives, we just store it in the proper collection

    [dbConnection readWriteWithBlock:^(YapCollectionsDatabaseReadWriteTransaction *transaction){
        [transaction setObject:messsage
                        forKey:uuid
                  inCollection:message.user_id
                  withMetadata:message.timestamp];
    }];
    

    So each message is stored separately. But it is placed in a collection with all other messages in the conversation. Further, adding a new message is fast because you're just adding a single row to the database.

    Internally the sqlite database looks like this: |collection|key|object|metadata|

    To find the number of conversations, or get the userIds for the conversations:

    [dbConnection readWithBlock:^(YapCollectionsDatabaseReadTransaction *transaction){
        conversationCount = [transaction numberOfCollections];
        conversationUserIds = [transaction allCollections];
    }];
    

    To get the number of messages in a conversation, or the ids of the messages:

    [dbConnection readWithBlock:^(YapCollectionsDatabaseReadTransaction *transaction){
        messageCount = [transaction numberOfKeysInCollection:user_id];
        messageIdsSorted = [transaction allKeysOrdered:NSOrderedAscending
                                          inCollection:user_id];
    }];
    

    To delete old messages from the database:

    [dbConnection readWriteWithBlock:^(YapCollectionsDatabaseReadWriteTransaction *transaction){
        [transaction removeObjectsEarlierThan:twoWeeksAgo inCollection:user_id];
    }];
    

    Hope this helps.