hotcakedev
hotcakedev

Reputation: 2504

How to use filter from an array while fetching graphql query and also must keep the array order?

I am trying to filter a result using an array and it should follow the order of the filter array.

Here's my array which will be used for filtering.

// gatsby-node.js

// Fetch all collections
  const collections = await graphql(`
    {
      allContentfulCollection {
        edges {
          node {
            handle
            productLists {
              slug
              handles
            }
          }
        }
      }
    }
  `);

  collections.data.allContentfulCollection.edges.forEach((collection) => {
    const { handle, productLists } = collection.node;

    if (productLists.length) {
      const defaultList = productLists.find(
        (productList) => productList.slug === 'default'
      );

      // example defaultList.handles =
      // [
      //  'test-handle-a',
      //  'test-handle-b',
      //  'test-handle-c',
      //  'test-handle-d'
      // ];

      createPage({
        path: `/collections/${handle}`,
        component: path.resolve('./src/templates/collection.js'),
        context: {
          handle,
          handles: defaultList && defaultList.handles // this will be used to filter
        }
      });
    }
  });
...
// templates/collection.js
export const query = graphql`
  query ProductInCollection($handles: [String], $handle: String) {
    allContentfulProduct(filter: { handle: { in: $handles }, availableForSale: { eq: true } }) {
      edges {
        node {
          handle
        }
      }
    }
    ...

The graphql result does not follow the sort of $handles array.

For example, the handle field which I get like the image is

enter image description here

[
  'test-handle-b', // this is matching result with test-handle-a
  'test-handle-d', // ...
  'test-handle-c', // ...
  'test-handle-a', // ...
]

// I expect to get the query result with the same order to the `$handles` in the query filter like below.

[
  'test-handle-a',
  'test-handle-b',
  'test-handle-c',
  'test-handle-d'
]

As you can see, I want to follow the ordering of the handles array, but I get an unexpected result like the above example.

How can I get the result with sort of the handles array?

Thank you.

Upvotes: 0

Views: 1237

Answers (1)

Ferran Buireu
Ferran Buireu

Reputation: 29320

It should take the filter order as it is. Are you sure that it always has the same order? Does it always contain the same information in the same order? Do they have any rules that you can use to sort them?

In your case, I'd try:

  createPage({
    path: `/collections/${handle}`,
    component: path.resolve('./src/templates/collection.js'),
    context: {
      handle,
      handles.sort() // add an specific rule if any
    }
  });

Moreover, you can try sorting the output via GraphQL sort:

// templates/collection.js
export const query = graphql`
  query ProductInCollection($handles: [String], $handle: String) {
    allContentfulProduct(filter: { handle: { in: $handles }, availableForSale: { eq: true } }, sort: { fields: [handle, $handles], order: ASC }) {
      edges {
        node {
          description
          handle
          title
        }
      }
    }
    ...

Despite adding the sorting in the GraphQL or JavaScript logic, I'd ensure that it has always the exact order. Additionally, if you can access the source of that array, you can try adding an order field to each array element.

Upvotes: 2

Related Questions