Мангуст Многие ко многим отношениям - PullRequest
0 голосов
/ 20 марта 2019

Я новичок в 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);

Я не знаю, хороша ли моя схема, требуется ли параметр person в моем userSchema? Поскольку информация будет дублироваться, в userSchema у меня будет personID, а в personSchema это будет userID.

Если я понимаю, полезно ли иметь эти дублированные значения для моих запросов? Но если информация дублируется, мне нужно выполнить два запроса для обновления двух таблиц?

Например, если у меня есть человек с семьей (параметр семьи в personSchema), а в семье у меня есть этот человек (параметр people в familySchema). Какие будут запросы на удаление / обновление строк в таблицах?

Спасибо

1 Ответ

1 голос
/ 20 марта 2019

ИМХО, ваша схема выглядит нормально, если она соответствует вашим потребностям !!(Хотя, если вы думаете, что ваша текущая схема выполняет вашу задачу без раздувания, то да, это нормально) ..

  1. Кажется, что «Персона» - это единственный тип пользователя и сущности, к которому нужно подключитьсяна отдых других лиц.Пока это так, вы можете свободно удалять параметр person из userchema, поскольку вы можете получить доступ к информации о пользователе от 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' }] 
});

Да, вам нужно будет обновить его как для отдельных лиц, так и для семьи, если вы хотите сохранить единообразие.Но это можно сделать за один запрос / мутацию.

Ну, вы можете выполнить запрос в зависимости от порядка потока вашей бизнес-логики.Допустим, «Гомер» - это человек , который является новым членом семьи Симпсонов .Таким образом, в этом случае вы добавляете «Гомер» в коллекцию «Семейство» (таблица), а затем помещаете ObjectId этого Симпсона (коллекция «Семейство») в сущность Person .

Я добавил пример примера добавления Гомера к семейству Симпсонов ниже.Надеюсь, это поможет:)

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

Если вы хотите выполнить обновление, то это зависит от цели вашей цели (например, если вы просто хотите обновить имя «Гомер», вы быобновлять его нужно только в коллекции Person, так как коллекция Family уже содержит ссылку на objectId Гомера, поэтому каждый раз, когда вы обновляете Homer, на обновленный документ будет ссылаться коллекция Family!) и

если вы хотите выполнить удаление, то и в этом случае подход будет отличаться в зависимости от сценария, как если бы вы хотели удалить документ о человеке, или просто удалить ссылку на человека из семьи, или удалить семьюрекомендация от лица !!

Допустим, вы хотите удалить человека, тогда в этом случае вам придется взять его и найти этого человека, и поскольку у вас есть доступ к семьям через этого человека, выможете получить доступ к семьям через person.families и удалить personId из соответствующих семей!И затем вы также можете удалить связанного пользователя, так как у вас есть ссылка на пользователя также из того же объекта person.

Подводя итог, это зависит от вашего выбора действий и от того, сколько санитарии вы хотите в своемсхема. Вышеупомянутый процесс был бы просто другим, если бы мы использовали другой подход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...