Realm on Android – How to select multiple objects by list of ids (@PrimaryKey)?-ThrowExceptions

Exception or error:

I’m building an Android app with the Realm database.

I have a RealmObject subclass called Article which has an id field (it’s and int and also a @PrimaryKey). I would like to pass to a query a list of ints (a Set, int[], or whatever) of article id’s and retrieve only those articles.

In SQL would be like this:

SELECT *
FROM `table`
where ID in (5263, 5625, 5628, 5621) 

I’ve seen it’s possible to do this in iOS in this StackOverflow question.

How can I do this in Android? Thanks!

Edit: Just to inform, I also asked this on the GitHub repo here.

How to solve:

Update:

Realm 1.2.0 has added RealmQuery.in() for a comparison against multiple values. The documentation details all the available overloads. This one is the method we can use if our ids are Integers:

public RealmQuery<E> in(String fieldName, Integer[] values)

Original answer:

The answer from @ChristianMelchior returns all articles if the list of ids is empty. I want it to return an empty RealmResults<Article>. That’s what I’ve ended up doing;

Set<Integer> articleIds = this.getArticleIds();
RealmQuery<Article> query = realm.where(Article.class);
if (articleIds.size() == 0) {
    // We want to return an empty list if the list of ids is empty. 
    // Just search for an id that does not exist.
    query = query.equalTo("id", -30000);
} else {
    int i = 0;
    for (int id : articleIds) {
        // The or() operator requires left hand and right hand elements. 
        // If articleIds had only one element then it would crash with
        // "Missing right-hand side of OR"
        if (i++ > 0) {
            query = query.or();
        }
        query = query.equalTo("id", id);
    }
}
return query.findAll();

###

Now realm v 1.2.0 support RealmQuery.in() for a comparison against multiple values.

###

The Realm Java API’s doesn’t support this yet unfortunately. You can follow the feature request here https://github.com/realm/realm-java/issues/841

The current work-around would be to build up the query yourself in a for-loop:

RealmResults<Article> articles = realm.allObjects(Article.class);
RealmQuery q = articles.where();
for (int id : ids) {
    q = q.equalTo("id", id);
}
RealmResults<Article> filteredArticles = q.findAll();

###

This is the way Realm does it since 1.2.0:

public RealmQuery<E> in(String fieldName, String[] values) {
    if (values == null || values.length == 0) {
        throw new IllegalArgumentException(EMPTY_VALUES);
    }
    beginGroup().equalTo(fieldName, values[0]);
    for (int i = 1; i < values.length; i++) {
        or().equalTo(fieldName, values[i]);
    }
    return endGroup();
}

Previously this is how I did it

###

I just came across this post and I thought I could throw in my 2 cents on this. As much as I appreciate Christian Melchior and his answers I think in this case his answer is not working (at least in the current version).

I prefer to do it like this – I personally think it’s more readable than Albert Vila’s answer:

List<String> listOfIds = [..];
RealmQuery<SomeClass> query = realm.where(SomeClass.class);

boolean first = true;
for (String id : listOfIds) {
    if (!first) {
        query.or();
    } else {
        first = false;
    }
    query.equalTo("id", id);
}
RealmResults<SomeClass> results = query.findAll();

Leave a Reply

Your email address will not be published. Required fields are marked *