简体   繁体   English

猫鼬多对多关系

[英]Mongoose Many to many relations

I'm new to mongoDB and Mongoose, and I have some problems with relations. 我是mongoDB和Mongoose的新手,并且在关系方面存在一些问题。 My schema has 3 tables (User / Person / Family), you can see it below. 我的架构有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);

I don't know if my schema is good, does the parameter person is require in my userSchema ? 我不知道自己的架构是否良好,在userSchema是否需要参数person Because the informations will be duplicated, in userSchema I will have the personID and in the personSchema this wil be the userID. 因为这些信息将重复,所以在userSchema我将具有personID,在personSchema中, personSchema是userID。

If I understand it's usefull to have this duplicated values for my requests ? 如果我了解将这些重复的值用于我的请求是否有用? But if the informations is duplicated I need to execute two queries to update the two tables ? 但是,如果信息重复,我需要执行两个查询来更新两个表?

For exemple, if I have a person with a family (families parameter in personSchema), and in the family I have this person (persons parameter in familySchema). 例如,如果我有一个家庭成员(personSchema中的family参数),而在家庭中我有这个人(familySchema中的persons参数)。 What will be the requests to remove / update the lines in the tables ? 删除/更新表中的行的请求是什么?

Thanks 谢谢

IMHO, your schema seems fine if it meets your needs !! 恕我直言,如果满足您的需求,您的架构就可以了! (Although, if you think your current schema fulfills your purpose without being bloated, then yeah its fine).. (尽管,如果您认为当前的架构可以实现您的目标而不会肿,那是可以的。)

  1. "Person" seems to be the only type of a user and the entity to be connected to rest of the other entities . “人”似乎是用户以及与其他实体连接的唯一实体。 As long as this is the case, you can feel free to remove the person parameter from the userschema as you can access the user information from the person. 只要是这种情况,您就可以随意从userschema中删除person参数,因为您可以访问来自person的用户信息。 But lets assume if there exists another entity "Aliens" who also has their own unique family, then it would be better to add the alien and person parameter in the "User" Schema to see the types of users.(As long as there's only one type ie Person, then you may not need to add it in userschema). 但是,假设存在另一个具有自己独特家族的实体“ Aliens”,那么最好在“ User”模式中添加Alien和person参数以查看用户类型。(只要存在一种类型,即“人”,那么您可能无需在userschema中添加它。 In case, if you still like to keep it, then please make the following change too in your schema as you are passing the array although it seems to be one to one relation ! 以防万一,如果您仍然希望保留它,那么在传递数组时也请在架构中进行以下更改,尽管这似乎是一对一的关系!

 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. Yes, you will need to update it for both entities Person and Family if you want to maintain the uniformity. 是的,如果您要保持统一性,则需要为“个人”和“家庭”两个实体都进行更新。 But, it could be done in one request/ mutation. 但是,可以在一个请求/更改中完成。

  2. Well, you could perform the request depending upon the flow order of your business logic. 好了,您可以根据业务逻辑的流程顺序执行请求。 Lets say if "Homer" is a Person who is a new member of the Simpson Family . 比方说,如果“荷马史诗”是谁的是辛普森家族的新成员。 So, in that case you would add "Homer" to the Family collection(table) and then push the ObjectId of this Simpson (Family collection) to the Person entity. 因此,在那种情况下,您可以将“荷马”添加到Family集合(表)中,然后将此Simpson(Family集合)的ObjectId推送到Person实体。

I have added the sample example of adding Homer to the Simpson family below. 我在下面添加了将荷马添加到Simpson系列的示例示例。 Hope this helps :) 希望这可以帮助 :)

 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; } } 

If you want to perform update, then it depends upon the intent of your purpose (as for example, if you just want to update the name "Homer", you would only have to update it in the Person collection, as the Family collection already has reference to the objectId of Homer, so every time you make an update to the Homer, the updated document would be referenced by Family collection ! ), and 如果要执行更新,则取决于目的(例如,如果您只想更新名称“荷马”,则只需在“人”集合中更新它,因为“家庭”集合已具有对Homer的objectId的引用,因此,每次对Homer进行更新时,Family collection都会引用更新的文档!),并且

if you want to perform deletion, then in that case too, the approach would be different based upon the scenario, as if you wish to remove a person document, or just remove the person reference from the family, or remove the family reference from the person !! 如果要执行删除操作,那么在这种情况下,方法也将根据情况而有所不同,就好像您要删除个人文档,或者只是从家庭中删除个人参考文献,还是从家庭中删除家庭参考文献一样。人!

Lets say you want to delete a person then in that case, you would have to take the personId and search for that person and since you have access to the families via this person, you can access the families via person.families and remove the personId from those respective families as well ! 假设您要删除一个人,那么在这种情况下,您将必须获取personId并搜索该人,并且由于您可以通过此人访问家庭,因此可以通过person.families来访问家庭并删除personId也来自那些各自的家庭! And then you could remove the associated user too as you have the reference to the user too from the same person object. 然后,您也可以删除关联的用户,因为您也可以从同一个人对象中引用该用户。

To sum up, it depends upon your choice of action, and how much sanitization you want in your schema.. The above mentioned process would be just different in case if we take a different approach. 总而言之,这取决于您选择的操作以及在模式中要进行多少清理。如果采用不同的方法,上述过程可能会有所不同。

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

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