Mongoose和MongoDB,与关系不同步

我错过了什么吗? 与传统数据库相比,为什么ORM需要更多努力来同步关系。 以下面的例子。

var UserSchema = new Schema({ username: {type: String, required: true, index:{unique:true}}, password: {type: String, required: true}, events: [{type: Schema.Types.ObjectId, ref:'Event'}] }); var EventSchema = new Schema({ _creator: {type:Schema.Types.ObjectId, ref: 'User'}, post: {type: String, required: true} }); 

UserSchema有许多事件,其中事件模式属于一个用户,也就是创build者。

 .delete(function(req, res){ Event.remove({ _id:req.params.event_id },function(err,response){ if(err) res.send(err); res.json({message:'Successfully Deleted'}); }); }); 

如果我创build一个事件并添加用户对象作为创build者,它会成功join表,但是如果我删除该事件。 事件不再显示,但ID仍显示在用户查询下。

下面是我删除属于用户的事件后,我的用户查询看起来像什么

 [ { "_id": "5831be814f8df40646fed954", "password": "$2a$10$MNbwpj0qi9.rhEPmCHe5mOc8crrEo/CwbxVSbjjLSw28GdcQ0O6Um", "username": "klaus", "__v": 1, "events": [ "5831c216a3d6810692bdf381" ] } ] 

我将如何去除用户架构的ID? 不把事件模式和用户模式联系起来会更好吗? 为什么这是一个屁股疼痛,为什么这是未来?

这不是一个ORM,没有连接,也没有表。 你正在尝试使用Mongo,就像它是一个关系数据库,事实并非如此。

回答你的问题“为什么这是一个屁股疼痛,为什么这是未来?” – 除非您将Mongo识别为文档存储并将其用于此目的,否则您将始终感到失望。

现在,有一些背景。 在关系数据库中,你可以有外键,约束和触发器,这些外键,约束和触发器可以确保当你在另一个关系中引用元组的时候,你不能删除元组,或者你可以删除它,但是操作级联并且删除现在指向不存在的密钥并导致数据库不一致。 这通常也在一个事务中完成,所以你可以确定没有人会看到数据的不一致的观点。

对于Mongo,没有这样的保证。 有validation,但可以绕过 。

当你存储对另一个文档的引用时,它只是一个String或者一个ObjectId实例,不必在任何地方存在于数据库中。 “引用比embedded提供了更多的灵活性,但是,客户端应用程序必须发出后续查询来parsing引用,换句话说,规范化的数据模型可能需要更多的往返服务器。 (参见规范化数据模型 )换句话说,不仅关系的有效性不被强制执行,实际的“连接”发生在客户端,而不是在数据库中,在一个单独的查询中(有可能的竞争条件)。

另外你没有事务,所以不可能在一个primefaces操作中删除一个文件和所有对它的引用。 但即使可能,Mongo中仍然没有模式,所以无论何时将ObjectId作为某个字段的值,Mongo都不知道应该引用哪个集合,所以它甚至不知道在哪里寻找。

这意味着您需要在删除可能在其他文档中引用的数据后手动清除。 但是由于数据库不会告诉你你正在删除的文档的ObjectId可能存储在哪里,所以你有责任了解并确保你自己保持数据库的一致性。

现在,为模式。 Mongo中确实没有schema的概念。 Mongoose中有模式,Mongo中没有。 “MongoDB中的数据具有灵活的架构 ,集合不强制文档结构。” (请参阅数据build模 )具有“灵活的模式”意味着根本没有模式。 在实践中,模式只存在于Mongoose的客户端。 您可以有一个很好的Mongoose模式,但是如果有多个应用程序连接到同一个数据库(甚至是同一个应用程序的两个版本),那么这些应用程序可能会有不一致的模式,并可能以静默方式损坏您的数据库。

考虑到这一切,我build议只有当你不需要保证一致性,交易,外键,连接,强制模式和其他function,你可能熟悉与其他数据库时,否则将使用Mongo总是像你描述的那样痛苦。