1

Suppose there is a table called RecentViewItem which stores recently viewed items by user. I want to keep only first 10 recently viewed items by deleting all other items. My query is like this:

RealmResults<RecentViewItem> results = 
    realm.where(RecentViewItem.class)
         .findAllSorted("updatedAt", Sort.DESCENDING);
// What to do next ?
iamcrypticcoder
  • 2,609
  • 4
  • 27
  • 50

2 Answers2

0
RealmResults<RecentViewItem> results = realm.where(RecentViewItem.class).findAllSorted("updatedAt", Sort.DESCENDING);
for(int i = 0, size = results.size(); i < 10 && i < size; i++) {
    RecentViewItem recentViewItem = results.get(i);
    recentViewItem.deleteFromRealm();
}
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • How about deleting first 1000 or suppose 10^5 rows ? Actually I am searching answer without loop. – iamcrypticcoder Dec 26 '16 at 17:48
  • You won't find a loopless answer unless you have an index that you can update for which you can define a query by which you can obtain a `RealmResults` on which you can call `deleteAllFromRealm()` – EpicPandaForce Dec 26 '16 at 17:55
  • I didn't understand your thought exactly, maybe you want a column by which you can get only first n rows and call deleteAllFromRealm(). it would be better if you elaborate plz. – iamcrypticcoder Dec 26 '16 at 18:07
  • @mahbub.kuet exactly. – EpicPandaForce Dec 26 '16 at 18:09
  • Realm does not know the concept of "number of rows", as far as I know. So you either loop, or you define a condition that gives you what you want. – EpicPandaForce Dec 27 '16 at 12:00
0

Since Realm for Java lazy loads its data, there isn't a LIMIT query which adds a bit of work. I query all the data sorted by a timestamp (in your case updatedAt).

Realm realm = Realm.getDefaultInstance();
final RealmResults<RecentViewItem> results = realm.where(RecentViewItem.class).findAllSorted("timestamp", Sort.DESCENDING);

I check whether it's over my limit and, if it is, get the result on the threshold so I can get its timestamp. Then I query against that threshold timestamp and delete all the results from before it.

if (results.size() > UPPER_LIMIT) {
    RecentViewItem firstOverLimit = results.get(TRUNCATE_LIMIT);
    // Assuming a system time. Maybe your updatedAt is a date. Could use an id too.
    long threshold = firstOverLimit.timestamp;
    final RealmResults<RecentViewItem> resultsToDelete = realm.where(RecentViewItem.class).lessThanOrEqualTo("timestamp", threshold).findAll();
    Log.d(TAG, "cleanUp: total "+ results.size() +
        "; over threshold of " + UPPER_LIMIT +
        "; truncating to " + TRUNCATE_LIMIT +
        "; deleting " + resultsToDelete.size() +
        "; all on or before "+ threshold);
    realm.executeTransaction(realm1 -> resultsToDelete.deleteAllFromRealm());
}

My TRUNCATE_LIMIT is half my UPPER_LIMIT so that this clean up does not run constantly as new records are added, but you can tune that however you like.

I'm also deleting the first record over the limit, but you can play with the boundary and retain it.

Also, my timestamp is quite exact but if your date is just "today" then you will get fuzzier results.

LordParsley
  • 3,808
  • 2
  • 30
  • 41