commercetools-jvm-sdk
commercetools-jvm-sdk copied to clipboard
Add helpers for prev/next like functionality (products)
@schleichardt it would be good to provide some helpers like
- [ ] hasPrev()
- [ ] hasNext()
- [ ] prev()
- [ ] next() which will calculate what would be the prev / next product based on the products list (PagedQueryResult) I pass to those helpers.
Do you know what I mean?
The interesting part in it is to keep the context, like reference expansion.
I don't know if it is possible, but it would be nice to have something like iterable, hasNext(): boolean, next(): Query<Product>
Well, my idea was that the helper should just do the calculation and accept only a PagedQueryResult. So the client has to keep track of the list (cache, session, ...) and use the helper to get something like a product or the prev/next query. The question is then, if the client has to fetch the next "page", should the helper do the async/sync request or let the client take care of it?
The "models" can't do actual http requests, you need to go through the client.
The client does not see play http related stuff.
For client I mean the shop (play application), not the java-client :)
Yes, this is an important issue, I think I will sit together with Laura to design this.
Cool
@schleichardt I did some research regarding this topic and it's actually simpler then it looks. Let me explain it a bit as it might give you some ideas how to implement this.
So products are a collection of documents and they have some indexes (_id
, createdAt
, ...). If you just query without any sorting criteria, mongo returns documents in a so called natural order which it's not reliable as it might change (e.g.: update operation). Providing a sorting criteria assures that you will always get reliable results.
So far nothing new.
So how to get the previous / next document? It turns out you just need to query for greater / less value and sort by that value asc / desc (respectively), and then limit the result to 1. That means getting the prev / next document works if you use sorting and query for the same value, and if the value is unique and hopefully has an index.
// example: get first 5 products sorted by createdAt.asc
db.products.find().sort({createdAt: 1}).limit(5).forEach(function(doc){
var o = {}
o.id = doc._id
o.createdAt = doc.createdAt
print(o)
})
// =>
/* 0 */
{
"id" : JUUID("8c574527-a160-4eec-99d3-7af8b0f99421"),
"createdAt" : "2014-08-03T09:27:02.690Z"
}
/* 1 */
{
"id" : JUUID("98f1006e-6338-4fbb-8683-492c68c7ba5c"),
"createdAt" : "2014-08-03T09:27:02.714Z"
}
/* 2 */
{
"id" : JUUID("1fb4147d-8b5f-4033-839d-3e0011d229fc"),
"createdAt" : "2014-08-03T09:27:02.740Z"
}
/* 3 */
{
"id" : JUUID("8a94097e-c394-46b5-b311-fbb3729bac0e"),
"createdAt" : "2014-08-03T09:27:02.771Z"
}
/* 4 */
{
"id" : JUUID("f7591242-2205-43b2-87ac-bdecf9952caf"),
"createdAt" : "2014-08-03T09:27:02.793Z"
}
// now let's find prev / next of second document
{
"id" : JUUID("98f1006e-6338-4fbb-8683-492c68c7ba5c"),
"createdAt" : "2014-08-03T09:27:02.714Z"
}
// previous document
db.products.find({createdAt: {$lt: "2014-08-03T09:27:02.714Z"}}).sort({createdAt: -1}).limit(1)
// =>
{
"id" : JUUID("8c574527-a160-4eec-99d3-7af8b0f99421"),
"createdAt" : "2014-08-03T09:27:02.690Z"
}
// next document
db.products.find({createdAt: {$gt: "2014-08-03T09:27:02.714Z"}}).sort({createdAt: 1}).limit(1)
// =>
{
"id" : JUUID("1fb4147d-8b5f-4033-839d-3e0011d229fc"),
"createdAt" : "2014-08-03T09:27:02.740Z"
}
This is what I discovered so far. If you have any suggestions or ideas I'll be happy to discuss them with you :)
@lauraluiz do we need that, how should it look like?
I think we need to put a bit more of helpers related to pages. In the end, we have a "Paged..." class. What I use to handle pagination are:
private static long calculateTotalPages(final PagedResult<?> result, final int pageSize) {
final Double totalPages = Math.ceil((float) result.getTotal() / pageSize);
return totalPages.longValue();
}
hasPrev
and hasNext
are the negated aliases from isFirst
and isLast
. We can also put them to make the code more semantically correct.
The next
and prev
versions I wouldn't use in my case because I don't have the previous search request by the time I need them, just a page.