Hi I am building an RESTful API in Node using mongoose to manage data on a practice food delivery site I am building.
I want to setup a patch route that will remove an order Item from my items array nested in my Orders document based on a request from the user identifying the specific item with a name or ID.
I have a patch route which pushes a new order item into the Items Array nested in the Orders document, I want this patch route to also be able to remove a specific Item from the array based on a prop such as name or ID
I have tried using the Update and UpdateOne methods and I think I'm just getting the syntax wrong or something as I keep getting errors.
Server.js:
require("dotenv").config()
const express = require("express");
const mongoose = require("mongoose");
const app = express();
mongoose.connect(process.env.DATABASE_URL)
const db = mongoose.connection
db.on("error", () => console.error(error))
db.once("open", () => console.log("connected to database"))
app.use(express.json())
const subscribersRouter = require("./routes/subscribers")
const suscribersLoginRouter = require ("./routes/login")
const restaurantsRouter = require("./routes/restaurants")
const ordersRouter = require("./routes/orders")
app.use("/subscribers", subscribersRouter)
app.use("/login", suscribersLoginRouter)
app.use("/restaurants", restaurantsRouter)
app.use("/orders", ordersRouter)
app.listen(3000, () => {
console.log("Server has started on port 3000")
});
Order Model:
const mongoose = require("mongoose")
const orderSchema = new mongoose.Schema({
userID: {
type: String,
required: true
},
total: {
type: Number,
required: true
},
items: {
type: Array,
required: true
}
})
module.exports = mongoose.model("order", orderSchema)
Orders Route (you will see here that I have a patch route which pushes a new order item into the Items Array nested in the Orders document, I want this patch route to also be able to remove a specific Item from the array based on a prop such as name or ID, the issue I am have is 1. How to create an if statement that gets the update of the item to be triggered and the the code id use in that if statement to actually update that Item)
const express = require("express")
const router = express.Router()
const Order = require("../models/order")
// Getting All
router.get("/", async (req, res) => {
try {
const orders = await Order.find()
res.json(orders)
} catch (err) {
res.status(500).json({
message: err.message
})
}
})
// Getting One
router.get("/:id", getOrder, (req, res) => {
res.json(res.order)
})
// Creating One
router.post("/", async (req, res) => {
const order = new Order({
userID: req.body.userID,
total: req.body.total,
items: req.body.items
})
try {
console.log(order)
const newOrder = await order.save()
res.status(201).json(newOrder)
} catch (err) {
res.status(400).json({
message: err.message
})
}
})
// Updating One
router.patch("/:id", getOrder, async (req, res) => {
if (req.body.userID != null) {
res.order.userID = req.body.userID
}
if (req.body.total != null) {
res.order.total = req.body.total
}
if (req.body.items != null) {
const currentItems = res.order.items
const newItem = req.body.items
currentItems.push(newItem)
}
try {
const updatedItems = await res.order.save()
res.json(updatedItems)
} catch (err) {
res.status(400).json({
message: err.message
})
}
})
// Deleting One
router.delete("/:id", getOrder, async (req, res) => {
try {
await res.order.remove()
res.json({
message: "Deleted Order"
})
} catch (err) {
res.status(500).json({
message: err.message
})
}
})
async function getOrder(req, res, next) {
let order
try {
order = await Order.findById(req.params.id)
if (order === null) {
return res.status(404).json({
message: "Cannot Find Order"
})
}
} catch (err) {
return res.status(500).json({
message: err.message
})
}
res.order = order
next()
}
module.exports = router
TEST Requests:
# ORDERS
# Get All
GET http://localhost:3000/orders
###
#Get One
GET http://localhost:3000/orders/627fe8e575a8229d0ae81e73
###
#Create One
POST http://localhost:3000/orders
Content-Type: application/json
{
"userID": "627f8b476fa64425928750c9",
"total":50,
"items": [
{
"name": "Burder",
"price": "R20",
"description": "A good Fuggen Waffel"
},
{
"name": "Hotdog",
"price": "R20",
"description": "A good Fuggen Waffel"
},
{
"name": "Bunny Chow",
"price": "R20",
"description": "A good Fuggen Waffel"
},
{
"name": "Pizza",
"price": "R20",
"description": "A good Fuggen Waffel"
}
]
}
###
#Delete One or all
DELETE http://localhost:3000/orders/628202c3b208aebc7f7f8f98
###
# Update on (add Order Item)
PATCH http://localhost:3000/orders/628202c3b208aebc7f7f8f98
Content-Type: application/json
{
"items": {
"name": "gravy",
"price": "R20",
"description": "A good Fuggen Waffel"
}
}
###
CodePudding user response:
I'm not sure I understood you correctly. I understood that you need the PATCH route to also delete an item from the items
array by name.
So here is my solution to it:
Because you already fetched the order and you just want to delete a specific item from the items
property, you can use filter
to do so before saving the order document.
res.order.items = res.order.items.filter(({ name }) => name !== itemNameToRemove);
Like this:
// Updating One
router.patch("/:id", getOrder, async(req, res) => {
const {
userID,
total,
items,
itemNameToRemove
} = req.body;
if (userID != null) {
res.order.userID = userID;
}
if (total != null) {
res.order.total = total;
}
if (items != null) {
const newItem = items;
res.order.items.push(newItem);
if (itemNameToRemove) {
res.order.items = res.order.items.filter(({
name
}) => name !== itemNameToRemove);
}
}
try {
const updatedItems = await res.order.save()
res.json(updatedItems)
} catch (err) {
res.status(400).json({
message: err.message
})
}
})
CodePudding user response:
you can use $pull for this.
Order.update(
{ userID : "userID123" },
{$pull : {"items" : {"name":"gravy"}}}
)
This will delete the object with name as gravy belong to the userID : userID123
Hope this helps!.