3

I want to make my PFQuery come in a random order, so the next time I'm creating the same PFQuery with limit it won't return the same objects as the first one.

PFQuery *query = [PFUser query];
[query orderBy...]; //Is there a randomOrder method?
                    //Or a workaround to get random order?
[query setLimit:10];

I need this to be in a random order every time, or else the PFQuery will contain the same 10 objects everytime

Peter
  • 1,848
  • 4
  • 26
  • 44

3 Answers3

5

You can't change the ordering of data returned in the query, but you can use paging to change the first object that is returned - so you could do something like this (it is based on the ToDo sample code from Parse but it will work for any object) -

PFQuery *query =[PFQuery queryWithClassName:@"Todo"];

NSInteger count=[query countObjects];
NSInteger skip = arc4random_uniform(count-10);

query.skip=skip;
query.limit=10;

NSArray *results=[query findObjects];

NSLog(@"object count=%d",results.count);

for (PFObject *object in results) {
    NSLog(@"text=%@",object[@"text"]);
}

You can now retrieve your 10 objects. for any given skip count they will be in the same order, but you could randomise the order after you retrieved the 10 items. Simply put them into an NSMutableArray and use technique in this answer - Re-arrange NSArray/MSMutableArray in random order

Note that this code isn't optimal as it doesn't perform the fetch tasks on the background thread. To use background threads you would use something like the following -

PFQuery *query =[PFQuery queryWithClassName:@"Todo"];


[query countObjectsInBackgroundWithBlock:^(int number, NSError *error) {

    query.skip=arc4random_uniform(number-10);;
    query.limit=10;

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (error) {
        NSLog(@"An error occurred - %@",error.localizedDescription);
        }
        else {
            NSLog(@"object count=%d",objects.count);

            for (PFObject *object in objects) {
                NSLog(@"text=%@",object[@"text"]);
            }
        }
    }];


}];
Community
  • 1
  • 1
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • If you give more information on why, perhaps I can help – Paulw11 Aug 21 '14 at 22:51
  • The query always contains the same 10 objects, in the same order, every time. I can't get this to do anything.. – Peter Aug 21 '14 at 23:03
  • I just updated my question with the exact code I have tested and it returns 10 different random objects each time – Paulw11 Aug 21 '14 at 23:31
  • Okey, thanks, I think I can use this. But can you explain exactly what happens when you set the skip here? Does it skip a (random number)*10 objects? – Peter Aug 24 '14 at 13:48
  • No, it just skips a random number of objects. The `limit=10` makes it return the next 10 rows after skipping `skip` rows, where skip is random between 0 and count-10. – Paulw11 Aug 24 '14 at 13:51
  • After implementing your code I get the error that says; `Warning: A long-running Parse operation is being executed on the main thread. Break on warnParseOperationOnMainThread() to debug.` How can I remove this? – Peter Aug 24 '14 at 14:22
  • I updated by answer to show how to use the Parse background functions with blocks – Paulw11 Aug 24 '14 at 21:27
  • Thanks again! One last question. Can the `countObjects number` be more than a 1000? Can the PFQuery contain more than 1000 a thousand objects? Cause I need the 10 objects I want to be chosen "randomly" from more than a 1000 objects. If you understand me.. :) – Peter Aug 24 '14 at 21:33
  • I just ran a test against a Parse table with 1298 rows and that is the number that was returned by `countObjectsInBackgroundWithBlock:` – Paulw11 Aug 24 '14 at 21:37
  • Okey, then I will assume this code will work, but will probably test it further later. But thanks anyways! Helped a lot! – Peter Aug 24 '14 at 21:41
0

PFQuery does not support random order but you can workaround this by creating an increasing index field to each object

Then given that you know the maxIndexin the table you can generate random indices as the following:

- (NSArray *)generateRandomIndices:(int)maxIndex limit:(int)limit {
    NSMutableArray  *indices = [[NSMutableArray alloc] initWithCapacity:limit];
    for (int i=0; i<limit; i++) {
        int randomIndex  = arc4random() % maxIndex;
        [indices addObject:[NSNumber numberWithInt:randomIndex]];
    }
    return indices;
}

Now you can query your class by using INpredicate

NSArray *randomIndices = [self generateRandomIndices:maxIndex limit:10];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"index IN %@", randomIndices];
PFQuery *query = [PFQuery queryWithClassName:@"className" predicate:predicate];
Mahmoud Adam
  • 5,772
  • 5
  • 41
  • 62
0

PFQuery don't give random objects. You can get all objects then randomize to get any 10 objects from it and show it.

Chetan
  • 2,004
  • 1
  • 13
  • 21