agaveazul
agaveazul

Reputation: 47

What is the best approach for referencing objectIds plus additional parameters in a schema?

I am creating a schema for an Order model that will track the items ordered along with the quantity purchased. I want to keep the itemId references and the quantity tied together as an array in one parameter.

I have created an Array that includes a reference to the ObjectId plus an additional Number type. I am currently unable to populate the product information using a .populate() query.

Order Schema

const mongoose = require("mongoose");
const { Schema } = mongoose;

const orderSchema = new Schema({
  orderNumber: String,
 _itemsOrdered: [
    {
      itemId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "menuItems"
      },
      quantity: Number
    }
  ]
});

mongoose.model("orders", orderSchema);

MenuItem Schema

const mongoose = require("mongoose");
const { Schema } = mongoose;

const MenuItemSchema = new Schema({
  imageURL: String,
  name_en: String,
  name_es: String,
  type_en: String,
  type_es: String,
  description_en: String,
  description_es: String,
  dietaryCallouts: [String],
  price: Number
});

mongoose.model("menuItems", MenuItemSchema);

module.export = MenuItemSchema;

I am able to save the record but cannot populate the MenuItem information with the following query:

Order Controller

  async show(req, res, next) {
    try {
      const orderId = req.params.id;

      let order = await Order.findById({ _id: orderId }).populate(
        "_itemsOrdered.itemId"
      );

      res.send(order);
    } catch (err) {
      res.status(402).send(err);
    }
  }

Here it the order object that is being saved to the DB.

Order Object

{
    "_id": "5dc93b9c0085b8045e0c8aa3",
    "orderNumber": "Order 3",
    "_itemsOrdered": [
        {
            "_id": "5dc93b9c0085b8045e0c8aa5",
            "itemId": "5dc7f814a2679b47319a79a4",
            "quantity": 1
        },
        {
            "_id": "5dc93b9c0085b8045e0c8aa4",
            "itemId": "5dc7e5c7de590744c46f93da",
            "quantity": 2
        }
    ],
    "__v": 0
}

Upvotes: 0

Views: 70

Answers (1)

SuleymanSah
SuleymanSah

Reputation: 17888

Your order schema must be like this:

const orderSchema = new Schema({
  orderNumber: String,
  _itemsOrdered: [
    {
      itemId: { type: mongoose.Schema.Types.ObjectId, ref: "menuItems" },
      quantity: Number
    }
  ]
});

And you can use the following route to create an order document.

router.post("/order", async (req, res, next) => {

  try {
    const { orderNumber, _itemsOrdered } = req.body;

    let order = new Order({ orderNumber, _itemsOrdered });
    order = await order.save();

    res.status(201).send(order);

  } catch (err) {
    console.log(err);
    res.status(500).send(err);
  }
});

Sample body: (you need to change ids according to yours)

{
    "orderNumber": "Order 1",
    "_itemsOrdered": [
        {"itemId": "5dc90346222b892434e4675a", "quantity" : 1 }, 
        {"itemId": "5dc90359222b892434e4675b", "quantity" : 2 }
    ]
}

To get the order and its items you can use populate like this:

router.get("/orders/:id", async (req, res) => {
  try {
    const orderAndItems = await Order.findById(req.params.id).populate(
      "_itemsOrdered.itemId"
    );

    res.send(orderAndItems);
  } catch (err) {
    console.log(err);
    res.status(500).send(err);
  }
});

This will give you a result like this:

{
    "_id": "5dc904db8407a217b4dfe6f4",
    "orderNumber": "Order 1",
    "_itemsOrdered": [
        {
            "_id": "5dc904db8407a217b4dfe6f6",
            "itemId": {
                "_id": "5dc90346222b892434e4675a",
                "name_en": "item 1",
                "price": 1,
                "__v": 0
            },
            "quantity": 1
        },
        {
            "_id": "5dc904db8407a217b4dfe6f5",
            "itemId": {
                "_id": "5dc90359222b892434e4675b",
                "name_en": "item 2",
                "price": 2,
                "__v": 0
            },
            "quantity": 2
        }
    ],
    "__v": 0
}

Upvotes: 1

Related Questions