猫鼬:具有相同架构键的模型之间的引用

时间:2019-07-31 11:04:09

标签: mongodb mongoose mongoose-schema mongoose-populate

作为前端开发人员,我想为两个isomorphic模型提供一些mongoose对象。

假设我有一个用户个人资料:

const profileSchema = new Schema({
  firstName: { type: String },
  lastName: { type: String },

  // example of difference between model schemas
  __user: { type: ObjectId, ref: 'Users' },
}

我想创建一个Contact的列表,其中每个联系人将具有一些相同的键:

const contactSchema = new Schema({
  firstName: { type: String },
  lastName: { type: String },

  __profile: {
    type: ObjectId,
    ref: 'Profiles',
    unique: true,
  },

  comment: { type: String }, 
}

注意: Contact可能两者都是:

  • 作为对Profile
  • 引用
  • 以及独立在DB / document中的记录。

=============================

我的问题:以这种方式组织模型的最好方法是,

  • 联系方式可能是个人资料的参考
  • 当类似的Profile键(例如firstName)被更新时,联系人firstName也将被更新

下一个引用的回避

await Contact.findById(SOME_ID).populate('__profile');

// result
{
  firstName: '',
  lastName: '',

  __profile: {
    firstName: 'Chuck',
    lastName: 'Norris',
  }
}

所需结果-保持联系“同构”,如:

{
  firstName: 'Chuck', // the key value from profile
  lastName: 'Norris', // the key value from profile

  __profile: SOME_PROFILE_ID,
}

这可能吗?

P.S:在我的应用中,我正在使用refs,并开始使用discriminators方法。

2 个答案:

答案 0 :(得分:1)

我会执行以下任务:

1)将所有数据放入1个集合中(例如个人资料):

// Profile model
{

  firstName: 'Chuck',
  lastName: 'Norris',

  contacts: [{
    type: ObjectId,
    ref: 'Profile',
    unique: true,
  }],
  ...all other properties

}

这样,您将能够仅存储联系人(例如,当我只想添加联系人时)和具有更多信息的个人资料。

2)或将使用区分符来创建基类(例如Contact)并在其上构建Profile模型:

const options = { discriminatorKey: 'userType' };

const Contact = mongoose.model('Contact', new mongoose.Schema({
    firstName: String,
    lastName: String
  },
  options)
)

const Profile = Contact.discriminator(
  'Profile',
  new mongoose.Schema(
    {
      contacts: [{
        type: ObjectId,
        ref: 'Contact',
        unique: true,
      }],
      comments: []
    },
    options
  )
);

这样,您将能够在1个集合中保存“联系人和个人资料”,并为“个人资料”中的联系人保存参考基类(Contact

希望有帮助!

答案 1 :(得分:0)

就我而言,Mongoose discriminators的完整使用并没有给我带来优势,因为歧视者为您提供了机会:

  

它们使您可以在具有重叠模式的多个模型上   基础MongoDB 集合的顶部。

因此,通过使用区分器方法,我将获得一个集合  的:

  • 个人资料

将有userscontact个人资料的组合。

=============================

所以我决定使用两种方法:

结果:

// keys which are same for both user Profile and Contact
const Schema = require('mongoose').Schema;
const util = require('util');

function BaseProfileSchema(...args) {
  Schema.apply(this, args);

  this.add({
    firstName: { type: String },
    lastName: { type: String },
  });
}
util.inherits(BaseProfileSchema, Schema);

// user Profile Model
const profileSchema = new BaseProfileSchema({
  __user: {
    type: String,
    ref: 'users',
    required: true,
    unique: true,
  },
});

const Profile = mongoose.model('profiles', profileSchema);

// Contact with profile as subdocument
const contactProfileSchema = new BaseProfileSchema();

const contactSchema = new Schema({
  // Associations
  __refProfile: {
    type: Schema.Types.ObjectId,
    ref: 'profiles',
    index: {
      unique: true,
      sparse: true,
    },
  },
  profile: contactProfileSchema,
});

const Contact = mongoose.model('contacts', contactSchema);

结果,我的数据库带有下一个集合:

  • 用户
  • 个人资料
  • 联系人

profilescontacts.profile都是相同的,因为我正在扩展基本共享模式。

此外:

  • Contact内部,我有不同的密钥用于真实引用的个人资料(__refProfile,其他人无法编辑)和contact.profile
  • profile内部连接只能在联系人自己编辑后才能编辑

P.S:幸福的dding语??