Filtering by dates in Gatsby and Contentful

2019-07-11 05:15发布

问题:

How can you filter by dates in Gatsby? The docs allude to lt and gt operators, I get errors when I try to use them.

回答1:

Filtering by date in Gatsby is potentially tricky. Many API's send dates in JSON as strings - in the ISO8601 format. That means that GraphQL will treat the dates as strings too. This is fine if you are happy filtering on string equality, but that's not usually how you want to filter on dates.

A common use case is to filter to dates that are in the past or future. In most situations, we would do some kind of less than or more than comparison with todays date. Unfortunately, this won't work for dates strings in GraphQL. The lt and gt operators only apply to numbers and won't work for strings.

Fortunately, there is an escape hatch - setFieldsOnGraphQLNodeType. This allows us to take a content node, and add our own fields with derived data in. We can take a datestring, and parse it to a timestamp - a number. With the date as a timestamp, graphql can do its thing and allow lt and gt filters.

Lets say we are writing a blog, and what to filter posts that are published in the past. We can add a publishedAt datetime field in our ContentModel, which will help our content authors publish things in the future. We can filter out the future posts until we transform publishedAt from a date string into a number.

Here's how that looks:

exports.setFieldsOnGraphQLNodeType = ({ type }) => {
  if (type.name === `ContentfulBlogPost`) {
    return {
      publishAtTimestamp: {
        type: GraphQLFloat,
        resolve: source => {
          return new Date(source.publishAt).getTime(); 
        }
     }
   };
  }

  // by default return empty object
  return {};
};

ContentfulBlogPost 's now have a new field publishedAtTimestamp which is a number, that means you can now filter on it with lt or gt

  query {
    allContentfulBlogPost(
      filter: { publishedAtTimestamp: { lt: $SOME_TIMESTAMP } }
    ) {
      edges {
        node {
          id
          ...otherFields
        }
      }
    }
  }