GraphQL - отношение возвращает ноль - PullRequest
0 голосов
/ 02 мая 2020

Я начал изучать GraphQL и пытаюсь создать следующие отношения:

type User {
  id: ID!,
  name: String!,
  favoriteFoods: [Food]
}

type Food {
  id: ID!
  name: String!
  recipe: String
}

Таким образом, в принципе, у пользователя может быть много любимых блюд, а еда может быть любимой у многих пользователей. Я использую graphql. js, вот мой код:

const Person = new GraphQLObjectType({
    name: 'Person',
    description: 'Represents a Person type',
    fields: () => ({
        id: {type: GraphQLNonNull(GraphQLID)},
        name: {type: GraphQLNonNull(GraphQLString)},
        favoriteFoods: {type: GraphQLList(Food)},
    })
})

const Food = new GraphQLObjectType({
    name: 'Food',
    description: 'Favorite food(s) of a person',
    fields: () => ({
        id: {type: GraphQLNonNull(GraphQLID)},
        name: {type: GraphQLNonNull(GraphQLString)},
        recipe: {type: GraphQLString}
    })
})

А вот данные о еде:

let foodData = [
    {id: 1, name: 'Lasagna', recipe: 'Do this then that then put it in the oven'},
    {id: 2, name: 'Pancakes', recipe: 'If you stop to think about, it\'s just a thin, tasteless cake.'},
    {id: 3, name: 'Cereal', recipe: 'The universal "I\'m not in the mood to cook." recipe.'},
    {id: 4, name: 'Hashbrowns', recipe: 'Just a potato and an oil and you\'re all set.'}
]

Так как я просто пытаюсь В общем, мой распознаватель просто возвращает пользователя, созданного внутри самого преобразователя. Мой мыслительный процесс заключался в следующем: поместите идентификаторы продуктов в GraphQLList , затем получите данные из foodData usind loda sh function find () и замените значения в person.favoriteFoods найденными данными.

const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    description: 'Root Query',
    fields: {
        person: {
            type: Person,
            resolve(parent) {
                let person = {
                    name: 'Daniel',
                    favoriteFoods: [1, 2, 3]
                }

                foodIds = person.favoriteFoods
                for (var i = 0; i < foodIds.length; i++) {
                    person.favoriteFoods.push(_.find(foodData, {id: foodIds[i]}))
                    person.favoriteFoods.shift()
                }

                return person
            }
        }
    }
})

Но последняя еда возвращает ноль. Вот результат запроса:

query {
  person {
    name
    favoriteFoods {
      name
      recipe
    }
  }
}

# Returns
{
  "data": {
    "person": {
      "name": "Daniel",
      "favoriteFoods": [
        {
          "name": "Lasagna",
          "recipe": "Do this then that then put it in the oven"
        },
        {
          "name": "Pancakes",
          "recipe": "If you stop to think about, it's just a thin, tasteless cake."
        },
        null
      ]
    }
  }
}

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

1 Ответ

1 голос
/ 02 мая 2020

Вызов shift и push для массива во время итерации по этому же массиву неизменно приведет к некоторым неожиданным результатам. Вы могли бы сделать копию массива, но было бы намного проще просто использовать map:

const person = {
  name: 'Daniel',
  favoriteFoods: [1, 2, 3],
}

person.favoriteFoods = person.favoriteFoods.map(id => {
  return foodData.find(food => food.id === id)
})

return person

Другая проблема заключается в том, что если ваша схема возвращает Person в другом преобразователе, вам придется дублировать эту логику c и в этом преобразователе. Что вы действительно должны сделать, это просто вернуть человека с favoriteFoods: [1, 2, 3]. Затем напишите отдельный преобразователь для поля favoriteFoods:

resolve(person) {
  return person.favoriteFoods.map(id => {
    return foodData.find(food => food.id === id)
  })
}
...