Фильтрация по датам в Gatsby и Contentful

Как можно фильтровать по датам в Гэтсби? Документы ссылаются на операторы lt и gt, я получаю ошибки, когда пытаюсь их использовать.


person Dom Barker    schedule 20.02.2019    source источник


Ответы (1)


Фильтрация по дате в Gatsby может оказаться сложной задачей. Многие API отправляют даты в JSON в виде строк - в формате ISO8601. Это означает, что GraphQL также будет обрабатывать даты как строки. Это нормально, если вам нравится фильтрация по равенству строк, но обычно это не так, как вы хотите фильтровать по датам.

Типичный вариант использования - фильтрация по датам в прошлом или будущем. В большинстве случаев мы бы сделали какое-то less than или more than сравнение с сегодняшней датой. К сожалению, это не сработает для строк дат в GraphQL. Операторы lt и gt применяются только к числам и не работают для строк.

Благо есть аварийный люк - setFieldsOnGraphQLNodeType. Это позволяет нам взять узел содержимого и добавить в него наши собственные поля с производными данными. Мы можем взять строку даты и преобразовать ее в метку времени - число. Используя дату в качестве метки времени, graphql может делать свое дело и разрешать фильтры lt и gt.

Допустим, мы пишем блог, а что фильтровать сообщения, опубликованные в прошлом. Мы можем добавить поле publishedAt datetime в нашу ContentModel, которое поможет авторам контента публиковать материалы в будущем. Мы можем отфильтровать будущие сообщения, пока не преобразуем publishedAt из строки даты в число.

Вот как это выглядит:

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 теперь имеет новое поле publishedAtTimestamp, которое представляет собой число, это означает, что теперь вы можете фильтровать его с помощью lt или gt

  query {
    allContentfulBlogPost(
      filter: { publishedAtTimestamp: { lt: $SOME_TIMESTAMP } }
    ) {
      edges {
        node {
          id
          ...otherFields
        }
      }
    }
  }
person Dom Barker    schedule 20.02.2019
comment
Очень хорошо, вы также можете сделать это в onCreateNode хуке (см. Этот вопрос). Мне нравится, что с setFieldsOnGraphQLNodeType вы можете указать тип поля. - person Derek Nguyen; 21.02.2019