Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LIMIT #544

Closed
gjcameron opened this issue Nov 9, 2014 · 28 comments
Closed

LIMIT #544

gjcameron opened this issue Nov 9, 2014 · 28 comments

Comments

@gjcameron
Copy link

@gjcameron gjcameron commented Nov 9, 2014

It would be very useful to be able to specify the maximum number of objects to return in a query, similar to LIMIT in SQL. Otherwise the RealmResults list must be manually trimmed with subList.

@cmelchior
Copy link
Contributor

@cmelchior cmelchior commented Nov 9, 2014

Hi Greg

Thank you for the feedback.

RealmResults are lazy loaded, so they don't take up additional memory whether you have 100 or 1.000.000 results.

Also the design intent was for RealmLists to behave like standard arrays, which means that subList() is the right way to do it.

However you are not the first to ask for a limit functionality, so either we have to be better about communicating the right use pattern or perhaps add limit as a shorthand for subList() like you suggested.

@cmelchior
Copy link
Contributor

@cmelchior cmelchior commented Nov 9, 2014

To clarify a little. While the results are lazy loaded in Android our Realm core does maintain a list of the results. However it is done in such a way that it is really lightweight and compact.

@gjcameron
Copy link
Author

@gjcameron gjcameron commented Nov 9, 2014

Thanks. Using subList works fine for me in most circumstances, the particular use case where I think it would be useful to be able to specify a limit in the query is when using an autoupdating RealBaseAdapter.

Perhaps this wasn't the intended use for the RealmBaseAdapter, but being able to specify a robust query for results (including sort order, as mention in my other enhancement request) that autoupdates would be very powerful.

@cmelchior cmelchior added the P1 label Apr 15, 2015
@cmelchior cmelchior changed the title No way to limit the number of objects retrieved in a query LIMIT Apr 15, 2015
@cmelchior cmelchior added the Blocked label Apr 16, 2015
@cmelchior cmelchior added P2 and removed P1 labels Apr 23, 2015
@bmunkholm bmunkholm added T-Feature and removed T-Enhancement labels Jun 13, 2015
@haskellcamargo
Copy link

@haskellcamargo haskellcamargo commented Jan 21, 2016

+1. Although the results are lazily loaded, subList is unsafe (IllegalArgumentException, IndexOutOfBoundsException) and specifying a value out of range will give a runtime error. This is particularly problematic when you deal with pagination, for example, If I want to take the values in a range of 100 starting by page 1:

List<Equipment> filtered;
try {
  filtered = results.subList((page - 1) * 100, page * 100);
 } catch (IndexOutOfBoundsException lastPage) {
  try {
    filtered = results.subList((page - 1) * 100, results.size());
  } catch (IllegalArgumentException noMoreData) {
    filtered = new ArrayList<>();
  }
}
@saket
Copy link

@saket saket commented Jan 21, 2016

@haskellcamargo Isn't it the dev's job to check the size before calling subList? I maintain a utility method subListSafely which does exactly this. This isn't the job of Realm IMO. :)

@haskellcamargo
Copy link

@haskellcamargo haskellcamargo commented Jan 21, 2016

Not exactly in this case. In case of LIMIT or TOP, we would securely have the values (also if we provided TOP 100 when we have only 50 items, and we lose the query abstraction that is provided by Realm. It is made to leave the boilerplate away. We lose an utility that is safely implemented by the relational databases and that is quite common. We mix the index check logic with the query logic (ah, and don't forget we have no extension methods in Java, like C#, to abstract it in a respectable way by extending RealmResult). I really believe that, as I said, although it is lazy, it would be useful to have a built-in feature for that and to keep the things clear. Abstraction and expressiveness are the way.

@cmelchior
Copy link
Contributor

@cmelchior cmelchior commented Jan 21, 2016

You would also have safety using Math.min/max:

int size = results.size();
results.subList(Math.max((page - 1) * 100, 0) , Math.min(page * 100, size));

That said we are not against adding some kind of LIMIT functionality as it can also have a positive impact on performance alongside the other benefits you mentioned. It does not have a high priority however, so I cannot give you any timeline for when we can add it.

@AlokBansal8
Copy link

@AlokBansal8 AlokBansal8 commented Feb 15, 2016

👍

3 similar comments
@jade-42
Copy link

@jade-42 jade-42 commented Mar 25, 2016

👍

@yemyatthu1990
Copy link

@yemyatthu1990 yemyatthu1990 commented Apr 6, 2016

👍

@olidroide
Copy link

@olidroide olidroide commented May 1, 2016

👍

@xiaolongyuan
Copy link

@xiaolongyuan xiaolongyuan commented May 24, 2016

+1

3 similar comments
@davroux
Copy link

@davroux davroux commented May 27, 2016

👍

@frogggias
Copy link

@frogggias frogggias commented Jul 29, 2016

👍

@carloseduardosx
Copy link

@carloseduardosx carloseduardosx commented Sep 19, 2016

👍

@Zhuinden
Copy link
Contributor

@Zhuinden Zhuinden commented Sep 19, 2016

@carloseduardosx I don't understand why you guys want a LIMIT.

All you need to do is SORT your RealmResults, and then do not index above your arbitrary threshold.

For example, in a Results that "contains" 225 elements, to obtain the second page (1 -> 2) of 50, all you need to do is index like this

// pageNum is 2
int min = (pageNum-1)*50;   //50
int max = pageNum*50;   //100, not inclusive
int size = realmResults.size(); // 225

// pageNum is 5
int min = (pageNum-1)*50;   //200
int max = pageNum*50;   //250, not inclusive
int size = realmResults.size(); // 225

Adapter:

public int getItemCount() {
    // assume pageNum = 5
    int min = (pageNum-1)*50;   //200
    int max = pageNum*50;   //250, not inclusive
    int size = realmResults.size(); // 225
    int elementCount = Math.min(max-min, size-min);
    return elementCount < 0 ? 0 : elementCount;
}

Then index

public void onBindViewHolder(RecyclerView.Holder holder, int position) {
     Element element = getItem(pageCount * 50 + position);
}

I did not test this but conceptually this is equivalent to a "LIMIT" as a query in terms of functionality in your application.

There is no point to limiting a Results. Just paginate your elements.

You guys don't even need subList. I don't understand why you are making your lives harder.

@Zhuinden
Copy link
Contributor

@Zhuinden Zhuinden commented Sep 19, 2016

Although I guess I can see a .skip(20).take(50) instead of limit().

@ahmadalibaloch
Copy link

@ahmadalibaloch ahmadalibaloch commented Sep 25, 2016

@Zhuinden And we don't understand why you guys dont implement the Limit query method to satisfy hundred people ;-). I need to use RealmResults for RecycleView (autoupdating) and need to limit results in a products suggestion page. I have spent 30 minutes exploring best way and then implementing custom way. its a basic feature in Library like Realm.
This is how I am doing:

RealmResults<Bayan> bayans = realm.where(Bayan.class).findAll();
List<String> bayanIds = Stream.of(bayans).limit(10).map(x -> x.Id).collect(Collectors.toList());
return realm.where(Bayan.class).in(BayanFields.ID, bayanIds.toArray(new String[])).findAll();
@Zhuinden
Copy link
Contributor

@Zhuinden Zhuinden commented Sep 25, 2016

@ahmadalibaloch hey, I'm just a community member, not an official realm person 👅

But to paginate the results, you just have to limit your index to show from the lowest and highest bound of your index, and show item size of the minimum of 30 or the remaining element count

I'd assume the reason why this is not trivial is because of minDate and the other additional methods of a result set that don't know how to evaluate themselves for a subset of the results

@beeender
Copy link
Contributor

@beeender beeender commented Dec 27, 2016

Another use case is to delete first n objects from a query results.
See http://stackoverflow.com/questions/41327579/how-to-delete-first-n-rows-in-realm

@cmelchior
Copy link
Contributor

@cmelchior cmelchior commented Jan 30, 2017

Core issue tracking this: realm/realm-core#1239

@dtmandroid
Copy link

@dtmandroid dtmandroid commented Apr 4, 2017

I have a Record Table. I want to display 5 records every time, user clicks on Next button until last record of Table. Please help me.. Thank you for your time...

@beeender
Copy link
Contributor

@beeender beeender commented Apr 4, 2017

@dtmandroid it is actually very simple, you could do something in your adapter:

public class MyAdapter {
private int baseIndex;

public void selectPage(int page) {
    baseIndex = 5 * page;
}

@Override
public void getIndex(int pos) {
    return adapterData.get(baseIndex + pos);
}

@Override
public void getCount() {
    return adapterData.size() - 5 > 0 ? 5 : adapterData.size() - baseIndex;
}

}

The above just shows the basic idea how to achieve you use case, I am sure you need to write more code to make a full implementation.

@dtmandroid
Copy link

@dtmandroid dtmandroid commented Apr 4, 2017

@beeender Thank for the answer. I could get first 5 records but crashes when get next 5 records. So will you please explain where to write selectPage() and getIndex() method and use of it.. Thank You,

@Zhuinden
Copy link
Contributor

@Zhuinden Zhuinden commented Apr 4, 2017

@dtmandroid you can also try this approach http://stackoverflow.com/a/38873498/2413303

@bmunkholm bmunkholm added S:Backlog and removed S:P2 Backlog labels May 18, 2017
@bmunkholm bmunkholm removed the S:Backlog label Aug 8, 2017
@null-dev
Copy link

@null-dev null-dev commented Apr 1, 2018

Please please please implement this. Calling size on RealmResults with > 20000 items can take 5+ seconds to complete. Lazy loading doesn't help so much when I don't know what is available to load!

@babedev
Copy link

@babedev babedev commented Jul 10, 2018

I also have problem with count() or `size. I have data over than 300K row it took about 3 seconds to finished counting.

Here is my code

realm.where(SomeClass::class.java)
  .findAll()
  .asFlowable()
  .map { it.count() }

I use findAll() with Flowable because I want to observe event on this table.

@Zhuinden
Copy link
Contributor

@Zhuinden Zhuinden commented Jul 10, 2018

You might want to try realm.where<SomeClass>().findAllAsync().asFlowable().filter { it.isLoaded() }

@cmelchior cmelchior mentioned this issue Aug 24, 2018
9 of 9 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet