1
votes

I have been searching for 2 days throughout docs, YouTube and GitHub projects to see if I could solve this problem. I am creating a pizza ordering system of which I have a few different GraphQL types. In this scenario, I have a Topping Type and a Pizza Type. The Pizza Type contains a toppings field which is an array of Topping type.

    type Topping {
        id: ID!
        name: String!
        price: Float!
        createdAt: String!
    }
    type Pizza {
        id: ID!
        location: String!
        price: Float!
        toppings: [Topping!]!
        createdAt: String!
        toppingCount: Int!
    }

The Mutation is:

    createPizza(pizzaInput: PizzaInput): Pizza!

    input PizzaInput {
        location: String!
        price: Float!
        toppings: [ID]! # How To Pass Existing Topping IDs Copied From DB?
        createdAt: String!
    }

Passing an array of IDs when calling the mutation within GraphQL playground results in many different errors relation to the structure of the toppings input.

mutation {
  createPizza(pizzaInput: {
    location:"Barcelona"
    price:12
    toppings: { # How To Structure This Input?
      create: [
        connect:"5faaca3129c74ff103d3ccaf"
        connect:"5fab01e8e0a1942d701fd408"
        connect:"5faaed887ac3c53010b8075b"
        connect:"5fab024de0a1942d701fd409"
        ]
    }
    createdAt:"Now"
  }){
    id
    price
    location
    toppings
    createdAt
    toppingCount
  }
}

Below is the create pizza mutation resolver:

    Mutation: {
        createPizza: async (
            _,
            { pizzaInput: { location, price, toppings, createdAt } }
        ) => {
            const { valid, errors } = validateCreatePizza(location, price);
            if (!valid) {
                throw new UserInputError("Errors", { errors });
            }

            const newPizza = Pizza({
                location,
                price,
                toppings,
                createdAt
            });

            console.log(newPizza);

            const pizza = await newPizza.save();
            return pizza;
        }
    }

Topping and Pizza Models:

const toppingSchema = new Schema({
    name: String,
    price: Number,
    createdAt: String
});
module.exports = model("Topping", toppingSchema);

const pizzaSchema = new Schema({
    location: String,
    price: Number,
    toppings: [
        {
            type: Schema.Types.ObjectId,
            ref: "toppings"
        }
    ],
    createdAt: String
});
module.exports = model("Pizza", pizzaSchema);
1
Is validateCreatePizza async? Also, how are you identifying your toppings in your db, for eg, by PK? How does that map to the ID scalar - Greg Brodzik
@GregBrodzik validateCreatePizza is not async. Just validates the fields and returns an errors object and a valid boolean. I'm using mongoose to model my DB schema. The ID for each mongo document is auto generated. - alanphil
of course in resolver you have only ids, not related objects/documents, you have to connect it in resolver ... get toppings by ids and pass to pizza as toppings or just save as is, depends on db/models - xadm
@xadm Just added the Topping and Pizza models. So you are saying to query the DB using the array of IDs? That seems like a lot of querying. - alanphil

1 Answers

0
votes

Modify your the structure of your input: i. separate each key/value pair passed as argument object, pizzaInput, with commas; ii. make price a float; iii. toppings in the context of your input type is an array of IDs -- update syntax to reflect that - remove create key and comma separate array values (there is no need to further nest the array in an object).

mutation {
  createPizza(pizzaInput: {
    location: "Barcelona",
    price: 12.00, 
    toppings: [
        "5faaca3129c74ff103d3ccaf",
        "5fab01e8e0a1942d701fd408",
        "5faaed887ac3c53010b8075b",
        "5fab024de0a1942d701fd409"
       ],
     createdAt: "Now"
    }
  }) {
    id
    price
    location
    toppings
    createdAt
    toppingCount
  }
}

FWIW, looking at your schema for Pizza type, unless a topping will always present, I would make that type nullable, that is, toppings: [Topping!].