繁体   English   中英

猫鼬多对多关系

[英]Mongoose Many to many relations

我是mongoDB和Mongoose的新手,并且在关系方面存在一些问题。 我的架构有3个表(用户/人/家庭),您可以在下面看到它。

var mongoose = require('mongoose')
, Schema = mongoose.Schema

var userSchema = Schema({
    _id       : Schema.Types.ObjectId,
    email     : String,
    person    : [{ type: Schema.Types.ObjectId, ref: 'Person' }] // A user is linked to 1 person
});

var personSchema = Schema({
    _id       : Schema.Types.ObjectId,
    name      : String,
    user      : [{ type: Schema.Types.ObjectId, ref: 'User' }]   // A person is linked to 1 user
    families  : [{ type: Schema.Types.ObjectId, ref: 'Family' }] // A person have 1,n families
});

var familySchema = Schema({
    _id       : Schema.Types.ObjectId,
    name      : String,
    persons   : [{ type: Schema.Types.ObjectId, ref: 'Person' }] // A family have 0,n persons
});

var User   = mongoose.model('User', userSchema);
var Person = mongoose.model('Person', personSchema);
var Family = mongoose.model('Family', familySchema);

我不知道自己的架构是否良好,在userSchema是否需要参数person 因为这些信息将重复,所以在userSchema我将具有personID,在personSchema中, personSchema是userID。

如果我了解将这些重复的值用于我的请求是否有用? 但是,如果信息重复,我需要执行两个查询来更新两个表?

例如,如果我有一个家庭成员(personSchema中的family参数),而在家庭中我有这个人(familySchema中的persons参数)。 删除/更新表中的行的请求是什么?

谢谢

恕我直言,如果满足您的需求,您的架构就可以了! (尽管,如果您认为当前的架构可以实现您的目标而不会肿,那是可以的。)

  1. “人”似乎是用户以及与其他实体连接的唯一实体。 只要是这种情况,您就可以随意从userschema中删除person参数,因为您可以访问来自person的用户信息。 但是,假设存在另一个具有自己独特家族的实体“ Aliens”,那么最好在“ User”模式中添加Alien和person参数以查看用户类型。(只要存在一种类型,即“人”,那么您可能无需在userschema中添加它。 以防万一,如果您仍然希望保留它,那么在传递数组时也请在架构中进行以下更改,尽管这似乎是一对一的关系!

 var userSchema = Schema({ _id : Schema.Types.ObjectId, email : String, person : { type: Schema.Types.ObjectId, ref: 'Person' } // A user is linked to 1 //person // Here I have removed the [] }); var personSchema = Schema({ _id : Schema.Types.ObjectId, name : String, user : { type: Schema.Types.ObjectId, ref: 'User' } // removed [] here too families : [{ type: Schema.Types.ObjectId, ref: 'Family' }] }); 

  1. 是的,如果您要保持统一性,则需要为“个人”和“家庭”两个实体都进行更新。 但是,可以在一个请求/更改中完成。

  2. 好了,您可以根据业务逻辑的流程顺序执行请求。 比方说,如果“荷马史诗”是谁的是辛普森家族的新成员。 因此,在那种情况下,您可以将“荷马”添加到Family集合(表)中,然后将此Simpson(Family集合)的ObjectId推送到Person实体。

我在下面添加了将荷马添加到Simpson系列的示例示例。 希望这可以帮助 :)

 addNewFamilyMember: async (_, {personID, familyID}) => { try{ let family = await Family.findOne({_id: familyID}); let person = await Person.findOne({_id: personID}); // created to push the objectId of the family in this if (!family){ throw new Error ('Family not found !') } else { let updatedFamily = await Family.findByIdAndUpdate( { _id: familyID }, { "$addToSet": { // "addToSet" inserts into array only if it does not exist already persons: personID } }, { new: true } ); person.families.push(updatedFamily); // pushing objectId of the Simpson family in Person "Homer" person = await person.save(); updatedFamily.persons.push(person); // pushing "Homer" in the Simpson family updatedFamily = updatedFamily.save(); return updatedFamily; } } catch(e){ throw e; } } 

如果要执行更新,则取决于目的(例如,如果您只想更新名称“荷马”,则只需在“人”集合中更新它,因为“家庭”集合已具有对Homer的objectId的引用,因此,每次对Homer进行更新时,Family collection都会引用更新的文档!),并且

如果要执行删除操作,那么在这种情况下,方法也将根据情况而有所不同,就好像您要删除个人文档,或者只是从家庭中删除个人参考文献,还是从家庭中删除家庭参考文献一样。人!

假设您要删除一个人,那么在这种情况下,您将必须获取personId并搜索该人,并且由于您可以通过此人访问家庭,因此可以通过person.families来访问家庭并删除personId也来自那些各自的家庭! 然后,您也可以删除关联的用户,因为您也可以从同一个人对象中引用该用户。

总而言之,这取决于您选择的操作以及在模式中要进行多少清理。如果采用不同的方法,上述过程可能会有所不同。

暂无
暂无

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

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