You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB中通过数组ID删除数组内的对象(Mongoose)

问题:删除MongoDB数组中指定的对象

我正在构建一个小型电影参考数据库,想要删除Movie文档里references数组中的单个对象。我的Mongoose Schema如下:

const movieSchema = new mongoose.Schema({
    title: {type: String, required: false},
    year: {type: String, required: false},
    image: {type: String, required: false},
    description: {type: String, required: false},
    plot: {type: String, required: false},
    references: [{title: String, reference: String, mediaType: String, timestampM: Number, timestampS: Number, description: String, relevance: String, refImg: String}]
})

目前已经实现了添加/编辑参考项的路由:

app.get('/movies/:id/edit', (req, res) =>{
    Movie.findById(req.params.id, (err, foundMovie) =>{
        res.render('editMovie.ejs', {movies: foundMovie})
    })
})

app.put('/movies/:id',  (req, res) => {
    Movie.findByIdAndUpdate(
        req.params.id,
        {
        $push: {
            references: req.body,
        }
        
    },{new:true}, (err, foundMovie)=> {
        
        res.redirect('/movies')
    })
    console.log(req.params.id)
})

我尝试了以下前端代码但没成功:

<% 
for (let i= 0; i < movies.references.length; i++) {
    %>
    
    <ul id="refList"> 
        <li id="movieReference" class="refTitle"><%= movies.references[i].reference%></li>
        <li id="movieSource"><p id="category"> Source Media:</p><p id="catInfo"><%= movies.references[i].mediaType %></p></li>
        <li id="movieTimestamp"><p id="category">Timestamp:</p><%=movies.references[i].timestampM %> minutes, <%=movies.references[i].timestampS %> seconds. <br> <br></li>
        <li id="movieDescription"><p id="category">Description: </p><%=movies.references[i].description%><br><br></li>
        <li id="catImg"><img class="boxImg" src="<%=movies.references[i].refImg%>"></li>
        <li id="delete"><button onclick="Movie.update(
            { $pull: { references: { id: movies.references[i].id}}},
            false,
            true,
            ); ">Delete Reference</button></li>
    </ul>
    
<% } %>

我需要的是仅删除数组中指定ID的对象,而非整个电影条目,请问我遗漏了什么?


解决方案

你当前的问题集中在三个核心点,按以下步骤修复即可:

1. 前端无法直接调用Mongoose方法

前端代码里直接写Movie.update()完全错误——Mongoose是后端Node.js库,前端浏览器无法直接访问数据库,必须通过后端API接口操作。

2. 新增后端删除路由

添加一个DELETE路由,接收电影ID和参考项的_id,用$pull操作符删除数组中匹配的对象:

// 先引入method-override中间件(后面会用到)
const methodOverride = require('method-override');
app.use(methodOverride('_method'));

// 删除单个参考项的路由
app.delete('/movies/:movieId/references/:refId', (req, res) => {
    Movie.findByIdAndUpdate(
        req.params.movieId,
        { $pull: { references: { _id: req.params.refId } } },
        { new: true },
        (err, updatedMovie) => {
            if (err) {
                console.error(err);
                return res.status(500).send(err);
            }
            res.redirect(`/movies/${req.params.movieId}/edit`);
        }
    );
});

3. 修改前端EJS代码

把删除按钮改成发送表单请求到新增的路由,注意要获取参考项自动生成的_id,同时避免重复ID(循环生成的元素不能用相同id,改成class):

<% for (let i= 0; i < movies.references.length; i++) { %>
    <ul class="refList">
        <li class="movieReference refTitle"><%= movies.references[i].reference%></li>
        <li class="movieSource">
            <p class="category">Source Media:</p>
            <p class="catInfo"><%= movies.references[i].mediaType %></p>
        </li>
        <li class="movieTimestamp">
            <p class="category">Timestamp:</p>
            <%=movies.references[i].timestampM %> minutes, <%=movies.references[i].timestampS %> seconds. <br><br>
        </li>
        <li class="movieDescription">
            <p class="category">Description:</p>
            <%=movies.references[i].description%><br><br>
        </li>
        <li class="catImg"><img class="boxImg" src="<%=movies.references[i].refImg%>"></li>
        <li class="delete">
            <form action="/movies/<%= movies._id %>/references/<%= movies.references[i]._id %>" method="POST">
                <input type="hidden" name="_method" value="DELETE">
                <button type="submit">Delete Reference</button>
            </form>
        </li>
    </ul>
<% } %>

额外注意

  • Mongoose默认会给数组里的每个子对象自动添加_id字段,如果你的数据里没有,可在Schema里显式定义:
    references: [{
        _id: mongoose.Schema.Types.ObjectId,
        title: String,
        // ...其他字段
    }]
    
  • 循环生成DOM元素时,不要用重复的id属性,否则会导致DOM选择器冲突,改用class。

内容的提问来源于stack exchange,提问作者Jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:21:26