GraphQL & Mongoose Schema - How to store an array of mongoose objectId references to another type?

Viewed 1154

I am currently developing a Pizza Ordering/Tracking system for my local pizzeria. As you can see below, I have the GraphQL types and Mongoose models defined. In my pizza, I have an array of toppings which I set to reference the topping model. My question is, what would my mutation definition and the call to that mutation with the required arguments look like?

I want my Pizza document in Mongoose to containt the relevant ToppingIds so I can reference other fields of that topping such as the name and price. Hope that's clear. Maybe an array is not the best way to approach this??

If there is a more efficient way to have toppings within the pizza model, pls do share.

GraphQL Types:

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

Mongoose Models:

const pizzaSchema = new Schema({
    location: String,
    price: Number,
    toppings: {
        type: Schema.Types.ObjectId,
        ref: "toppings"
    },
    createdAt: String
});

const toppingSchema = new Schema({
    name: String,
    price: Number,
    createdAt: String
});

So ideally when viewing a pizza in the database, it should look like:

_id: ObjectId("5fab2e6cc4b5e628685228f6")
> toppings:Array
[
    ObjectId("5fab2e6cc4b5e628685228f7")
    ObjectId("5fab2e6cc4b5e628685228f8")
]
location:"Barcelona"
price:123
createdAt:"12"
__v:0

Thanks in advance.

Edit: My Mutation Type and Mutation Call/Args + Error Message

createPizza(pizzaInput: PizzaInput): Pizza!
input PizzaInput {
    location: String!
    price: Float!
    toppings: [ID]!
    createdAt: String!
}

mutation {
  createPizza(pizzaInput: {
    location:"Barcelona"
    price:12
    toppings: [
      "5faaca3129c74ff103d3ccaf"
      "5faaed887ac3c53010b8075b"
    ]
    createdAt:"AAAA"
  }){
    id
    price
    location
    toppings {
      id
    }
    createdAt
    toppingCount
  }
}

Error Message: "ID cannot represent value: <Buffer 5f aa ca 31 29 c7 4f f1 03 d3 cc af>"

1 Answers

I believe you'll need the toppings value in the pizzaSchema to reflect that it is an array. Currently, it is just defined as an object like this:

    toppings: {
        type: Schema.Types.ObjectId,
        ref: "toppings"
    },

Instead of (note the brackets indicating an array):

    toppings: [{
        type: Schema.Types.ObjectId,
        ref: "toppings"
    }],

Or in full, it should look like this:

const pizzaSchema = new Schema({
    location: String,
    price: Number,
    toppings: [{
        type: Schema.Types.ObjectId,
        ref: "toppings"
    }],
    createdAt: String
});

Update after your edit:

Do you have a resolver defined for Pizza.toppings? I'm guessing that you're missing something like this in your resolvers map:

  Pizza: {
    toppings: (parent) => {
      const obj_ids = parent.toppings.map((id) => ObjectId(id));
      return Topping.find({ _id: { $in: obj_ids } });
    },
  }

I'm not a GraphQL expert so I'm not sure if there is a more efficient way to have toppings within the pizza model, but based on a test I did adding the above resolver gets passed the "ID cannot represent value..." issue.

Related