Forum

Thread tagged as: Question, Runway

Order Collection By Multiple Fields

Hi all,

I have a requirement that means i have to do some jiggery pokery to output a list of items in a order that means some are "sticky" and others just flow in the order they were posted.

I had this working with a small subset of data, but now that more data is in, i can see that the original solution wont work and i need to do a two column sort to get the "sticky" items to sort first and then the rest after.

I did see a thread from 2 years ago that said multiple sort fields wasn't available at the time but may come in, but can't seem to see any documentation on it if it has. If not i may have to do two database calls and get separate lists and smash them together, but trying to avoid that if possible.

Thanks

Roberto Modica

Roberto Modica 0 points

  • 4 years ago

I believe you will have to do the initial filter with a function() callback which will allow you to do additional filtering of the data.

Otherwise, you can always filter and skip-template, then do additional sorting of data then template and output.

Drew McLellan

Drew McLellan 2638 points
Perch Support

I would use a composite field that includes the contents of the two fields, and then sort by that composite field.

Drew McLellan said:

I would use a composite field that includes the contents of the two fields, and then sort by that composite field.

https://docs.grabaperch.com/templates/field-types/composite/

Why do I always forget composite fields exist...

Robert Ketter said:

I believe you will have to do the initial filter with a function() callback which will allow you to do additional filtering of the data.

Otherwise, you can always filter and skip-template, then do additional sorting of data then template and output.

Not 100% sure i understand this, is there a direct callback with perch_collection or is this PHP? PHP is not my most proficient language so i might miss some of the details.

Drew McLellan said:

I would use a composite field that includes the contents of the two fields, and then sort by that composite field.

Hi Drew,

This might work actually, can i use _date in a composite field?

Guess i may find out :)

Thanks,

Rob

Duncan Revell

Duncan Revell 78 points
Registered Developer

You'll have to use the date components to make up the composite - so:

date_day date_month date_year

Duncan Revell said:

You'll have to use the date components to make up the composite - so:

date_day date_month date_year

Thanks Duncan!

Drew McLellan said:

I would use a composite field that includes the contents of the two fields, and then sort by that composite field. Hi Drew,

Can i use _id in a composite field, i have created the following, but it doesn't seem to work, the pos-lock appears but not the id?

<perch:content id="sort-field" type="composite" for="pos-lock _id" join="-" />
Drew McLellan

Drew McLellan 2638 points
Perch Support

No, you can't use _id.

Right, i have something but its not working correctly. I have the composite field and it looks like this:

<perch:content id="sort-field" type="composite" for="pos-lock created-date_day created-date_month create-date_year created-date_hour created-date_minute" join="-" />

Which, for items created via the admin are fine. But part of the need for this wonky sort is the collection is intergrated with an Instagram feed which pulls in posts on a schedule, and the composite does not seem to get set when the item is created, and i can't seem to set it when using the collection importer (which actually i kinda get) but not the part where its not being generated, so for example my import scheduled task code is:

foreach($posts as $post){

      if(!post_already_exists($post->id, $dbPosts)){
        try {
          $datePosted = new DateTime();
          $datePosted->setTimestamp($post->created_time);

          $year = $datePosted->format('Y');
          $month = $datePosted->format('m');
          $day = $datePosted->format('d');
          $hour = $datePosted->format('H');
          $minute = $datePosted->format('i');
          $sortFieldFormat = '0-%s-%s-%s-%s-%s';
          $sortField = sprintf($sortFieldFormat, $year, $month, $day, $hour, $minute);

          $Importer->add_item([
            'type'            => 'Instagram',
            'title'           => 'Instagram Post',
            'title_2'         => $post->id,
            'secondary-title' => '',
            'body'            => $post->caption->text,
            'expando'         => '1',
            'pos-lock'        => '0',
            'color'           => '',
            'image-url'       => $post->images->standard_resolution->url,
            'created-date'    => $datePosted->format('Y-m-d H:i:s'),
            'sort-field'      => $sortField
          ]); 
        } catch (Exception $e) {
          die('Error: '.$e->getMessage());
        }
      }
    }

this just sets sort-field to '0', with or without trying to populate it in the importer.

if i can get the composite to work with the importer i am golden, if not i am stuck.

Drew McLellan

Drew McLellan 2638 points
Perch Support

What happens if you declare it as a text field in the template the importer uses?

Drew McLellan said:

What happens if you declare it as a text field in the template the importer uses?

Not sure why using a different template didn't pop in my head! Thanks Drew, that seems to work.

Thank you.