Mongodb 猫鼬:如何避免重复文档?

Mongodb 猫鼬:如何避免重复文档?,mongodb,mongoose,database-schema,nosql,Mongodb,Mongoose,Database Schema,Nosql,我为一些评论设计了一个收藏。 审阅集合架构包含帖子和主题。 帖子属性(键、电话、日期、内容、作者姓名)是评论集合的直接子项。 主题属性(键、标题)是主题对象的子对象,它是审阅集合的子对象。 每篇文章都属于一个主题。 每个帖子键都是唯一的,每个主题键都是唯一的。 如果许多帖子属于一个主题,那么每次评论都会重复主题数据(NoSQL不是ACID,对吗?:-) 问题是:复制主题属性的决定是否正确,或者我应该为帖子和主题使用不同的集合 这是我的模型: var reviewSchema = new mong

我为一些评论设计了一个收藏。
审阅集合架构包含帖子和主题。
帖子属性(键、电话、日期、内容、作者姓名)是评论集合的直接子项。
主题属性(键、标题)是主题对象的子对象,它是审阅集合的子对象。
每篇文章都属于一个主题。
每个帖子键都是唯一的,每个主题键都是唯一的。
如果许多帖子属于一个主题,那么每次评论都会重复主题数据(NoSQL不是ACID,对吗?:-)

问题是:复制主题属性的决定是否正确,或者我应该为帖子和主题使用不同的集合

这是我的模型:

var reviewSchema = new mongoose.Schema({
  key: String,
  phone: String,
  date: Date,
  contents: String,
  author: {
    name: String,
  },
  topic: {
    key: String,
    title: String,
  },
});
reviewSchema.index({ 'key': 1 }, { unique: true });
reviewSchema.index({ 'phone': 1 }, { unique: false });
reviewSchema.index({ 'topic.key': 1 }, { unique: false });

如果您希望避免重复,请为
主题
创建一个单独的架构,然后在您的
评论中引用它:

var TopicSchema = new mongoose.Schema({
    key: String,
    title: String
});

var ReviewSchema = new mongoose.Schema({
    key: String,
    phone: String,
    ...
    topic: {type: Schema.Types.ObjectId, ref: 'Topic'}
});

var Topic = mongoose.model('Topic', TopicSchema);
var Review = mongoose.model('Review', ReviewSchema);
从这里开始,当您想插入带有
主题的
审阅
作为子文档时,请使用
populate()
。基于您在自己的文档中存储<代码>作者<代码>的事实,您可以考虑在那里遵循相同的模式。

我对你使用
键感到好奇。默认情况下,MongoDB在顶级文档上创建一个唯一的
\u id
,这是一种主键。如果这是您对
键的意图,那么您可能应该让MongoDB来处理它

但归根结底,你的问题没有“正确”的解决方案,只有权衡的比较。MongoDB的一个优点是能够轻松地“存储您查询的内容”,而且由于
主题
非常小,如果您每次获取评论时都想要主题,那么复制这些主题可能是值得的。MongoDB不是集合中的ACID(我不能说其他NoSQL选项),因此使用这种方法,一次更新所有嵌入主题可能会导致用户出现短暂的差异

// Get entire review in one go, including subdocuments!
Review.findOne( { "key": "myReview" }, (err, doc) => { /* do things */ } );

// On bulk topic updates, not all topics change at once (not ACIDic)
Review.update(
  { topic.title: 'foo' },
  { topic.title: 'bar' },
  { multi: true },
  (err, doc) => {/* callback */ }
);
如果您来自SQL背景,那么上面描述的
populate()
范例会让您感觉舒服得多。由于MongoDB是针对每个文档的,所以对一个主题更新一次就足以满足所有其他引用它的文档。在幕后,这将要求Mongoose至少进行两次查询:一次查询
审查
,然后再次查询引用的
主题

// To replace refs with documents two queries behind the scenes
Review.findOne( { key: 'myReview' } )
  .populate('topic').exec( (err, review) => { /* do things */ })

// But updating a single topic is ACIDic, since reviews only contain references
Topic.update( { key: 'foo' }, { title: 'sci-fi' }, (err, res) => {/* more stuff */ } )

根据我的经验,除非您将查询管道推到极限,并希望不惜一切代价缩短响应时间,否则使用
populate()
的单独模式值得权衡额外的查询。

如果您希望避免重复,请为
主题创建单独的模式,然后在
评论中引用它

var TopicSchema = new mongoose.Schema({
    key: String,
    title: String
});

var ReviewSchema = new mongoose.Schema({
    key: String,
    phone: String,
    ...
    topic: {type: Schema.Types.ObjectId, ref: 'Topic'}
});

var Topic = mongoose.model('Topic', TopicSchema);
var Review = mongoose.model('Review', ReviewSchema);
从这里开始,当您想插入带有
主题的
审阅
作为子文档时,请使用
populate()
。基于您在自己的文档中存储<代码>作者<代码>的事实,您可以考虑在那里遵循相同的模式。

我对你使用
键感到好奇。默认情况下,MongoDB在顶级文档上创建一个唯一的
\u id
,这是一种主键。如果这是您对
键的意图,那么您可能应该让MongoDB来处理它

但归根结底,你的问题没有“正确”的解决方案,只有权衡的比较。MongoDB的一个优点是能够轻松地“存储您查询的内容”,而且由于
主题
非常小,如果您每次获取评论时都想要主题,那么复制这些主题可能是值得的。MongoDB不是集合中的ACID(我不能说其他NoSQL选项),因此使用这种方法,一次更新所有嵌入主题可能会导致用户出现短暂的差异

// Get entire review in one go, including subdocuments!
Review.findOne( { "key": "myReview" }, (err, doc) => { /* do things */ } );

// On bulk topic updates, not all topics change at once (not ACIDic)
Review.update(
  { topic.title: 'foo' },
  { topic.title: 'bar' },
  { multi: true },
  (err, doc) => {/* callback */ }
);
如果您来自SQL背景,那么上面描述的
populate()
范例会让您感觉舒服得多。由于MongoDB是针对每个文档的,所以对一个主题更新一次就足以满足所有其他引用它的文档。在幕后,这将要求Mongoose至少进行两次查询:一次查询
审查
,然后再次查询引用的
主题

// To replace refs with documents two queries behind the scenes
Review.findOne( { key: 'myReview' } )
  .populate('topic').exec( (err, review) => { /* do things */ })

// But updating a single topic is ACIDic, since reviews only contain references
Topic.update( { key: 'foo' }, { title: 'sci-fi' }, (err, res) => {/* more stuff */ } )

根据我的经验,除非您将查询管道推到极限,并希望不惜一切代价缩短响应时间,否则使用
populate()
的单独模式值得权衡额外的查询。

谢谢!确保此类数据的重复是可以接受的,这对我来说很重要…:-)绝对地如果答案有帮助,请接受。再等几天就可以得到更完整的答案了…:-)谢谢确保此类数据的重复是可以接受的,这对我来说很重要…:-)绝对地如果答案有帮助,请接受。再等几天就可以得到更完整的答案了…:-)