繁体   English   中英

如何在MongoDB中删除文档和所有嵌入式文档?

[英]How to remove document and all embedded documents in MongoDB?

我在Mongoose中定义了以下架构:

var postSchema = mongoose.Schema({
  title: String,
  body: String,
  created: Date,
  photos: Array
});

var Post = mongoose.model('Post', postSchema);

var photoSchema = mongoose.Schema({
  filename: String,
  mimetype: String,
  data: Buffer,
  created: Date
});

var Photo = mongoose.model('Photo', photoSchema);

如果我删除Post ,我也希望所有相关的Photo也要删除(例如在SQL中级联删除)。

如果我执行Post.remove({ _id: MY_POST_ID }) ,则仅删除Post ,并且我的孤儿Photo留在数据库中。

另外,我应该以某种方式在“ Photo架构中定义帖子ID吗?

获得真正原子操作的唯一方法是实际使用嵌入式模型,如下所示:

var photoSchema = mongoose.Schema({
  filename: String,
  mimetype: String,
  data: Buffer,
  created: Date
});

var postSchema = mongoose.Schema({
  title: String,
  body: String,
  created: Date,
  photos: [photoSchema]
});

var Post = mongoose.model('Post', postSchema);

然后,您实际上可以使用一个简单的语句删除所有内容,因为它们都在同一集合中,并且实际上在同一文档中:

Post.remove({ "_id": postId },function(err) {
   // handling in here
});

使用当前架构,您将需要单独删除所有文档:

var async = require("async");

var photoSchema = mongoose.Schema({
  filename: String,
  mimetype: String,
  data: Buffer,
  created: Date
});

var Photo = mongoose.model('Photo', photoSchema);

var postSchema = mongoose.Schema({
  title: String,
  body: String,
  created: Date,
  photos: [{ "type": Schema.types.ObjectId, "ref": "Photo" }]
});

var Post = mongoose.model('Post', postSchema);

// later

async.waterfall(
    [
        function(callback) {
            Post.findById(postId,callback);
        },

        function(post,callback) {
            Photo.remove({ "_id": { "$in": post.photos } },function(err) {
               if (err) callback(err);
               callback();
            });
        },

        function(callback) {
            Post.remove(photoId,callback);
        }
    ],
    function(err) {
       if (err); // do something
       // Job done
    }
)

如果您想避免先阅读文档,那么您可以

var photoSchema = mongoose.Schema({
  postId: Schema.types.ObjectId,
  filename: String,
  mimetype: String,
  data: Buffer,
  created: Date
});

然后删除与“帖子”相关的所有“照片”,然后发出:

Photo.remove({ "postId": postId },function(err) {
   // removed or err
});

一般而言,如果您始终希望这种行为,并且带有所有嵌入的“照片”信息的“发布”文档不能增长到16MB以上,则嵌入选项最有意义,因为您实际上不需要使用“照片”除了单亲的孩子之外,其他任何地方。

如果添加的照片仅属于一个Post ,则可以将所有照片嵌入Post模式中。 您可以通过在Post模式中将照片对象推送到photos数组来实现。 然后,您的Post文档将具有以下结构:

{
    title: 'My-first-post',
    body: 'Lorem ipsum',
    created: '01-01-1900',
    photos: [
        { filename: 'file1', mimetype: 'type', data: 238947289347239874, created: '01-02-1900' },
        { filename: 'file2', mimetype: 'type', data: 238947284321225671, created: '02-02-1900' }
    ]
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM