Storing relationships in Realm (Java)

642 views Asked by At

I'm starting to use Realm to store objects in my Android app. Here's an example of what I'm looking to store:

public class Item implements RealmModel {
    String id;
    ...
}

I have multiple lists that display items. The number of lists can keep expanding (the user can create as many lists as possible.

Let's say the user create's a list called "Best". When I'm viewing the "Best" list I call getItems("Best") which gets a List<Items> from the API. I now have to figure out how to store this list. In SQLite world I would have create a new table "custom_list_best", for example, which is just a single list of all the Item.id's that are part of the list. I would also have an "items" table that has all the distinct Items. To get items in the best list I would simply do a join query on both the best and items tables.

In the Realm world I'm trying to figure out how Realm works and what's the best way to build my models.

I initially thought I could create an object called CustomList:

public class CustomList implements RealmModel {
    String listId;
    RealmList<Item> items;
}

I would then store a RealmList<CustomList>. But the only issue is I also want to be able to query against all Items. So I need to also store a RealmList<Item> in Realm. How does Realm work in this case? If I store a separate RealmList<Item> and then store each RealmList<CustomList> will it not duplicate data?

Instead will I have to manually handle this by doing this instead:

public class CustomList implements RealmModel {
    String listId;
    List<String> itemIds;
}

And then query for Item.class objects that have itemId in itemIds from above object?

1

There are 1 answers

0
EpicPandaForce On BEST ANSWER

In SQLite world I would have create a new table "custom_list_best",

No, you would have a table called custom_lists with an auto-increment ID and an identifier, and a join table called join_custom_lists_items that would contain the ID of custom_lists and the ID of any item that belongs to that given custom list.

In the Realm world I'm trying to figure out how Realm works and what's the best way to build my models.

If the ID of the item is concrete and you need to be able to store the same Item in multiple lists, then in order to access the lists in both directions, you'll need a RealmList<? extends RealmModel> in both cases.

@RealmClass
public class Item implements RealmModel {
    @PrimaryKey
    private String id;

    private RealmList<CustomList> customLists;

    // getter setter
}

And

@RealmClass
public class CustomList implements RealmModel {
    @PrimaryKey
    private String title; // assuming you cannot name two lists the same? otherwise do `@Index`

    private RealmList<Item> items;

    // getter setter
}

This way you can do

realm.executeTransaction(new Realm.Transaction() {
  public void execute(Realm realm) {
    Item item = realm.where(Item.class).equalTo(ItemFields.ID, itemId).findFirst(); // assuming exists
    CustomList customList = realm.where(CustomList.class).equalTo(CustomListFields.TITLE, "Best").findFirst();
    if(customList == null) {
         customList = realm.createObject(CustomList.class, "Best");
    }
    customList.getItems().add(item);
    item.getCustomLists().add(customList);
  }
}

And then you can query

RealmResults<Item> bestItems = realm.where(Item.class)
                                    .equalTo(ItemFields.CustomLists.TITLE, "Best")
                                            //same as "customLists.title"
                                    .findAll();

All this Fields stuff I'm using is from https://github.com/cmelchior/realmfieldnameshelper