如何更新嵌套在文档中的数组中的特定项目

How to Update a specific Item in an array nested in a document

您好,我正在 Node 中构建一个 RESTful API,使用 mongoose 来管理我正在构建的实践食品配送网站上的数据。

我想设置一个补丁路由,根据用户的请求从我的订单文档中嵌套的项目数组中删除一个订单项目,该请求用名称或 ID 识别特定项目。

我有一个补丁路由,它将一个新的订单项目推送到嵌套在订单文档中的项目数组中,我希望这个补丁路由也能够根据名称等道具从数组中删除一个特定的项目或 ID

我已经尝试使用 Update 和 UpdateOne 方法,但我认为我只是语法错误或不断出现错误。

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")
});

订购型号:

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(你会在这里看到我有一个补丁路由,它将一个新的订单项目推送到嵌套在 Orders 文档中的 Items 数组中,我希望这个补丁路由也能够从基于名称或 ID 等道具的数组,我遇到的问题是 1. 如何创建一个 if 语句来获取要触发的项目的更新以及该 if 语句中使用的代码 id 来实际更新该项目)

    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

测试请求:

# 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"
    }
    
}

###

我不确定我是否理解正确。我知道您需要 PATCH 路由来按名称从 items 数组中删除一个项目。 所以这是我的解决方案: 因为您已经获取了订单并且您只想从 items 属性 中删除特定项目,所以您可以在保存订单文档之前使用 filter 执行此操作。

res.order.items = res.order.items.filter(({ name }) => name !== itemNameToRemove);

像这样:

// 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
    })
  }
})

你可以为此使用 $pull。

Order.update(
  { userID : "userID123" },
  {$pull : {"items" : {"name":"gravy"}}}
)

这将删除具有 name 的对象,因为 gravy 属于用户 ID:userID123