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

$pages->find("sort=random") doesn't work as expected across pagination #266

Open
Toutouwai opened this Issue May 20, 2017 · 4 comments

Comments

Projects
None yet
3 participants
@Toutouwai

Toutouwai commented May 20, 2017

Short description of the issue

When "sort=random" is used in a $pages->find() selector and the results are paginated, a new random sort is applied on each results page. This means that an item may appear more that once across the paginated results, and navigating back to or reloading a results page shows different results each time.

Expected behavior

The random sorting is applied only once across paginated results.

Optional: Suggestion for a possible fix

A solution is to use RAND(N) in the SQL query instead of RAND(), where N is a seed value.

Not sure if there's a good way to be smart about automatically storing and using a seed across pagination so the user (i.e. PW developer) doesn't need to do anything special.

Or if the existing behaviour for the 'random' keyword should be kept and a new keyword introduced for when a seed should be used, e.g. 'random($seed)' where $seed is an integer supplied by the user. It would be up to the user to supply a seed where needed and keep that across the pagination via GET or session variable. Of course this would be more demanding on the user than an automatic solution.

See also

Related forum thread: https://processwire.com/talk/topic/16313-using-a-seed-when-getting-random-pages/

@LostKobrakai

This comment has been minimized.

Show comment
Hide comment
@LostKobrakai

LostKobrakai May 21, 2017

Collaborator

Not sure if there's a good way to be smart about automatically storing and using a seed across pagination so the user (i.e. PW developer) doesn't need to do anything special.

Using a custom session value generated on login should suffice for basic usecases. But as this is not really random – not each refresh is random – it should probably be a new keyword. Maybe randomSession or so. With something like $session->refreshRandomSeed() the dev could handle user initiated reshuffling of content.

Another option of storage would be a second GET parameter for pagination, but this one should be toggleable and not enabled by default.

Collaborator

LostKobrakai commented May 21, 2017

Not sure if there's a good way to be smart about automatically storing and using a seed across pagination so the user (i.e. PW developer) doesn't need to do anything special.

Using a custom session value generated on login should suffice for basic usecases. But as this is not really random – not each refresh is random – it should probably be a new keyword. Maybe randomSession or so. With something like $session->refreshRandomSeed() the dev could handle user initiated reshuffling of content.

Another option of storage would be a second GET parameter for pagination, but this one should be toggleable and not enabled by default.

@Toutouwai

This comment has been minimized.

Show comment
Hide comment
@Toutouwai

Toutouwai May 22, 2017

Re: automatic seed - the challenge is that at the time the initial random-sorted $pages->find() is done it's not known if "limit=x" will be used for just a single results PageArray or as part of paginated results.

I had some thoughts about an approach where a hash is created from the selector components (excluding start and limit) and a random integer also generated for use in RAND(N). Then the integer is stored in a session variable named by the hash. On subsequent find() operations a check is made to see if a session variable exists for that hash and if so the integer is used in RAND(N).

But perhaps overly complicated?

Toutouwai commented May 22, 2017

Re: automatic seed - the challenge is that at the time the initial random-sorted $pages->find() is done it's not known if "limit=x" will be used for just a single results PageArray or as part of paginated results.

I had some thoughts about an approach where a hash is created from the selector components (excluding start and limit) and a random integer also generated for use in RAND(N). Then the integer is stored in a session variable named by the hash. On subsequent find() operations a check is made to see if a session variable exists for that hash and if so the integer is used in RAND(N).

But perhaps overly complicated?

@LostKobrakai

This comment has been minimized.

Show comment
Hide comment
@LostKobrakai

LostKobrakai May 22, 2017

Collaborator

But perhaps overly complicated?

That.

The random seed will probably always be bound to the session and different selectors yield different results therefore different sorting anyways. So one seed per session should in theory be enough.

Collaborator

LostKobrakai commented May 22, 2017

But perhaps overly complicated?

That.

The random seed will probably always be bound to the session and different selectors yield different results therefore different sorting anyways. So one seed per session should in theory be enough.

@ryancramerdesign

This comment has been minimized.

Show comment
Hide comment
@ryancramerdesign

ryancramerdesign May 26, 2017

Contributor

I don't think that tying the existing "sort=random" to a seed is a good way to go here, because the intention with it is that it returns a random set. Previous calls are not meant to influence later calls. After all, someone may be doing multiple similar random calls in the same request. If a seeded sort=random is needed as a new feature, then I think we'd go with the sort=random.$seed, similar to what's suggested in the first post.

Contributor

ryancramerdesign commented May 26, 2017

I don't think that tying the existing "sort=random" to a seed is a good way to go here, because the intention with it is that it returns a random set. Previous calls are not meant to influence later calls. After all, someone may be doing multiple similar random calls in the same request. If a seeded sort=random is needed as a new feature, then I think we'd go with the sort=random.$seed, similar to what's suggested in the first post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment