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
}
}
}
}