wp-graphql/wp-graphql-acf

Feature request: Sort / Order by custom field.

BartoszLobejko opened this issue ยท 15 comments

Currently, there is no way to sort posts by custom fields. So in case scenario that is probably quite common where for example, you have Custom Post Type: Events and then you would add Advanced Custom Field: Start Date. You're not able to sort by Start Date.

I guess there are some workarounds but it would be great to have Sort by ACF.

@BartoszLobejko By sort you mean something like this?

query GetPosts($customField: String){
  query getPosts(first: 10, where: {
     customField: $customField
   }){
      slug  
   }
}

If so, that would be great!

More like below. This example is with a date but it could be anything. Plus here you have filtering on top that shows only records after a certain date.

query EventsQuery {
    events(
      where: {
        orderby: {
          field: CUSTOM_DATE_FIELD,
          order: DESC
        }
        dateQuery: {
          after: {
            year: 2019,
            month: 03,
            day: 15
          }
        }
      }
    ) {
        nodes {
        ...EventItem
        }
    }
  }

Yep, I played with meta queries but in my understanding it only let you filter by custom field but not to order by it. So I could replace part of example above to get only dates after specific date but then I wouldnโ€™t be able to sort them in DESC order.

Correct me if Iโ€™m wrong.

@BartoszLobejko Yes you're right. It would be a great improvement indeed.

@BartoszLobejko Last night i was playing a bit around with wp-graphql and reading some docs of the acf wp plug, and i end up with a nice solution. You can modify the PostObjectsConnectionOrderByEnum.php file of the wp-graphql plugin and add the following line of code inside the register_graphql_enum_type function:

'META'     => [
	'value'       => 'meta_value',
	'description' => __( 'Order by meta value', 'wp-graphql' ),
]

and then make queries like this:

{
  trekking(first:1, where: {
    orderby: {
      field: META,
      order: ASC
    }
	 metaQuery: {
           metaArray: [
             {
               key: "start_date"
               value: "01/09/2019"
               compare: GREATER_THAN
             }
          ]
     }
  }){
    nodes {
      id
      trekkingId
      slug
      attributes {
        price
        startDate
        durationCategory
      }
    }
  }
}

Of course, you should use this with the wp-graphql-meta-query plugin.
Hope it helps! :)

This solution looks great! Hopefully, you can push this to Master repo for release. I use Composer to pull or plugins so I don't want to mess up with plugin core code. What I did, for now, is: Every time the user saves the post theme function duplicates Meta start_date to post_date. This way I can use build-in sorting.

But I will definitely use your solution when it gets to release or have a different use case.

Thank you. @Emiliano-Bucci

@BartoszLobejko Happy that helps! I admit i never did pr for this project, but definitely i will try it! :)

I tried the same method

query GetDocumentAndTags {  
  contentDetails(where: {orderby: {field: META, order:DESC}
  	metaQuery: {
           metaArray: [
             {
               key: "order"
             }
          ]
    }}
  ) {
    edges {
      node {
        id
        order
      }
    }
  }
}

only the first result gets ordered
Result

{
  "data": {
    "contentDetails": {
      "edges": [
        {
          "node": {
            "id": "Y29udGVudDoxMTI=",
            "order": 7
          }
        },
        {
          "node": {
            "id": "Y29udGVudDoxMTA=",
            "order": 5
          }
        },
        {
          "node": {
            "id": "Y29udGVudDoxMjI=",
            "order": 15
          }
        },
        {
          "node": {
            "id": "Y29udGVudDoxMjA=",
            "order": 12
          }
        },
        {
          "node": {
            "id": "Y29udGVudDoxMDg=",
            "order": 1
          }
        }
      ]
    }
  }
}

@ParthChugh I think that, in this case, you should also specify type: NUMERIC in your meta array object. I encounter similar issues with ordering results by numeric values. Let me know if this solve your issue :)

Yes it actually worked, Thanks for the fast response :)

@ParthChugh Happy that worked! :)

Is there any news on this feature or if is going to be implemented? :)

This is a pretty complicated feature to implement in a programatic way.

I don't have a good idea on how to handle this in a performant way. Meta Queries are traditionally poor for WordPress performance, and querying/filtering by ACF meta is often worse. ACF data isn't stored in a way that is efficient for querying/filtering by.

Short term, filtering by ACF meta will need to be handled on a case-by-case basis in the implementing application.

There is this GIST which might be helpful: https://gist.github.com/jasonbahl/da87dbccb58f1323a324a9b3e8952d6c

This YouTube video should also be helpful:
https://www.youtube.com/watch?v=-mZhAe63k3U

Currently we're not planning to support this feature in this version or the upcoming rewrite being worked on here: https://github.com/wp-graphql/wpgraphql-acf

I would love to support this at some point, but my comment above still stands true, that meta queries are typically very expensive and can even take sites down.

We might explore this as an opt-in feature of some sort in the future, where you can enable it, understanding the associated risks. But for the moment this will not be supported by the core WPGraphQL for ACF plugin.