MongoDB (Mongoose) data structure question

喜夏-厌秋 提交于 2020-04-16 09:55:55

问题


I'm curious about the best way to represent this kind of situation in Mongo. I have my own idea, but I'm curious on what the general consensus/best practice actually would be.

Imagine I have two collections:-

Employees
 --> _id
 --> FirstName
 --> Surname
 --> Email

Comments
  --> _id
  --> PersonReference
  --> CommentDate
  --> Comment

Now imagine that Employees can come and go and the 'Employees' collection is always up-to-date. However, in the event that an employee has ever made a comment, the full information on the comment including who made it must be available.

The way I would propose to tackle this problem, is to organise the structure like this instead:-

Employees
 --> _id: _id
 --> FirstName: string
 --> Surname: string
 --> Email: string

Comments
  --> _id: _id
  --> CommentDate: date
  --> Comment: string
  [-] --> PersonReference
  [+] --> Employee: object { _id: id, FirstName: string, Surname: string, Email:string }

So essentially, I would have a list of 'Active Employees' and at a time where a comment is made, I would duplicate the employee information into the Comments collection document (rather than use a reference).

From a high level perspective, is this considered best practise?

Many thanks


回答1:


Duplicating the employee info in the comments collection is really a bad idea. When an employee info needs to be changed, it will also needs to be updated in the comments.

You have a few options:

1-) Embedding the comments inside the Employee schema:

In this method we have no separate Comments collection.

If you have no need to independently query comments, this method makes sense. This way we can access a user and his/her comments in one db access and without needing any join (populate or lookup).

The schema for this can be like this:

const mongoose = require("mongoose");

const employeeSchema = new mongoose.Schema({
  firstName: String,
  username: String,
  email: String,
  comments: [
    new mongoose.Schema({
      commentDate: Date,
      comment: String
    })
  ]
});

module.exports = mongoose.model("Employee", employeeSchema);

2-) Parent referencing:

In this method we keep the reference of the comments in the Employee schema. If you don't need to access to employee from a comment, this can an option.

Employee Schema:

const mongoose = require("mongoose");

const employeeSchema = new mongoose.Schema({
  firstName: String,
  username: String,
  email: String,
  comments: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Comment"
    }
  ]
});

module.exports = mongoose.model("Employee", employeeSchema);

Comment Schema:

const mongoose = require("mongoose");

const commentSchema = new mongoose.Schema({
  commentDate: Date,
  comment: String
});

module.exports = mongoose.model("Comment", commentSchema);

3-) Child referencing

In this method we keep reference of the employee in the comments. So if you need to access the comments from an employee we need to use Populate Virtual feature of mongoose. Becase in employee schema we don't have a reference to the comments.

Employee Schema:

const mongoose = require("mongoose");

const employeeSchema = new mongoose.Schema(
  {
    firstName: String,
    username: String,
    email: String
  },
  {
    toJSON: { virtuals: true } // required to use populate virtual
  }
);

// Populate virtual
employeeSchema.virtual("comments", {
  ref: "Comment",
  foreignField: "employee",
  localField: "_id"
});

module.exports = mongoose.model("Employee", employeeSchema);

Comment Schema:

const mongoose = require("mongoose");

const commentSchema = new mongoose.Schema({
  commentDate: Date,
  comment: String,
  employee: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Employee"
  }
});

module.exports = mongoose.model("Comment", commentSchema);

4-) Both parent and child referencing:

With this method, it is possible to select comments from employee, and employee from comments. But here we have some kind of data duplication, and also when a comment is deleted, it needs to be done in both of the collections.

const mongoose = require("mongoose");

const employeeSchema = new mongoose.Schema({
  firstName: String,
  username: String,
  email: String,
  comments: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Comment"
    }
  ]
});

module.exports = mongoose.model("Employee", employeeSchema);

Comment Schema:

const mongoose = require("mongoose");

const commentSchema = new mongoose.Schema({
  commentDate: Date,
  comment: String,
  employee: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Employee"
  }
});

module.exports = mongoose.model("Comment", commentSchema);



回答2:


Many database implement kind of no-delete collections, implementing a delete/active flag for each document.

For example, Employees collection would become :

Employees
 --> _id: _id
 --> FirstName: string
 --> Surname: string
 --> Email: string
 --> Active: boolean

This way, you keep track on employees data that has been deleted, and prevent documents duplication if you have database size restrictions.

PS: nowadays you can be tackled keeping user data if they ask deletion (RGPD)


EDIT: This solution with boolean may not work if Employees document is updated and you want to keep employees firstname,name,mail,etc at the time he made the Comment.



来源:https://stackoverflow.com/questions/59235301/mongodb-mongoose-data-structure-question

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!