GraphQL: фильтрация данных в массиве

Я уверен, что это простая вещь, но я ничего не мог найти ни в документе GraphQL, ни в Graphcool.

скажем, у меня есть сущность с этой схемой (новый пользователь GraphQL, извините, если я ошибаюсь в представлении схемы):

Book {
  name: String!
  author: String!
  categories: [String!]
}

как бы я сделал запрос для всех книг, которые являются частью "mystery" категория? Я знаю, что могу фильтровать с allBooks(filter: {}), а categories_in: ["mystery"] и categories_contains: "mystery" трюк не сработал.

2 ответов


Category модель

подумав немного больше об этой ситуации, создавая Category модель, безусловно,путь.

например, представьте, что вы хотите, чтобы позволить читателям подписаться на свои любимые категории позже. Или, что, если вам нужен список всех существующих категорий? Используя списки строк, вам нужно будет запросить все книги и каким-то образом обработать все полученные категории. Обработка этого на уровне модели, а не с помощью списков строк чувствует себя намного больше природный.

вместо этого вы можете создать новый Category модель и добавить отношение "многие ко многим" между Category и Book. В таких ситуациях мне нравится добавлять уникальное поле перечисления tag и в строке text. (Уникальное строковое поле tag один также был бы подходящим, вероятно, вопрос вкуса.)

С этой установкой, вы можете легко выполнить требования к данным как

книги, которые назначаются с учетом категория?

query {
  # query books by unique category tag
  Category(tag: MYSTERY) {
    books {
      id
    }
  }
  # query books by specific category text
  Category(filter: {
    text: "mystery"
  }) {
    books {
      id
    }
  }
}

какие книги относятся по крайней мере к одной категории данного списка?

query {
  allCategories(filter: {
    OR: [{
      tag: MYSTERY
    }, {
      tag: MAGIC
    }]
  }) {
    books {
      id
    }
  }
}

какие книги назначаются всем категориям данного списка?

query {
  allCategories(filter: {
    AND: [{
      tag: MYSTERY
    }, {
      tag: MAGIC
    }]
  }) {
    books {
      id
    }
  }
}

соответствующих фильтров

несмотря на то, что вышеуказанные запросы удовлетворяют указанным требованиям к данным, Книги группируются по Category в ответе, что означает, что нам придется сгладить группы на клиент.

С так называемыми связанными фильтрами мы можем повернуть это, чтобы получить книги только на основе условий, определенных его связанными категориями.

например, на запрос книги, отнесенные по крайней мере к одной категории данного списка:

query {
  allBooks(filter: {
    OR: [{
      categories_some: {
        tag: MYSTERY
      },
      categories_some: {
        tag: MAGIC
      }
    }]
  }) {
    id
  }
}

если вы заинтересованы в использовании размещенного сервиса GraphQL, скафолд.Ио имеет эту функцию в течение некоторого времени. Все поля подключения в вашем API поставляются с WhereArgs аргумент, который предоставляет фильтры, которые позволяют вам действительно копаться в ваших данных. Когда у вас есть список скаляров, подобных этому, WhereArgs включают contains & notContains поле, которое позволяет фильтровать результаты на основе значений в списке. Это позволяет сделать такой запрос.

query MysteriousBooks($where:BookWhereArgs) {
  viewer {
    allBooks(where:$where) {
      edges { node { title, ... } }
    }
  }
}

# Variables
{
  "where": {
    "categories": {
      "contains": "mystery"
    }
  }
}

просто чтобы быть полным, вы также можете выполнить небольшую корректировку схемы, чтобы сделать эту работу без фильтрации скалярного списка. Например, вы можете сделать Category тип реализации узла, а затем создайте соединение между Category и Book. Хотя Book вероятно, не будет иметь много категорий, это позволит вам выдать такой запрос:

query MysteriousBooks($where: CategoryWhereArgs) {
  viewer {
    allCategories(where: $where) {
      books {
        edges { node { title, ... } }
      }
    }
  }
}

# Variables
{
  "where": { 
    "name": { 
      "eq": "mystery" 
    } 
  }
}

если вы структурируете свою схему таким образом, вы также сможете сделать больше фильтрации в книгах в категории без необходимости просматривать каждую книгу в вашем архиве. Например, вы могли бы эффективно попросить " все таинственные книги, написанные в прошлом году."

полное раскрытие: я работаю в Scaphold, и хотя я бы хотел, чтобы вы не испытывали никаких обид, если вы не переключитесь. Я рад видеть, что люди пытаются и любят GraphQL. Если вам интересно, о том, как реализовать этот тип поведения на вашем сервере, дайте мне знать, и я буду рад помочь там!

Я надеюсь, что это помогает!