MongoDB (Mongoose) 数据结构问题
MongoDB (Mongoose) data structure question
我很好奇在 Mongo 中表现这种情况的最佳方式。我有自己的想法,但我很好奇一般的 consensus/best 实践究竟是什么。
假设我有两个 collections:-
Employees
--> _id
--> FirstName
--> Surname
--> Email
Comments
--> _id
--> PersonReference
--> CommentDate
--> Comment
现在想象一下,员工可以来来去去,'Employees' collection 总是 up-to-date。但是,如果员工发表过评论,则必须提供评论的完整信息,包括评论者。
我建议解决这个问题的方法是组织这样的结构:-
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 }
所以基本上,我会有一个 'Active Employees' 的列表,并且在发表评论时,我会将员工信息复制到评论 collection 文档中(而不是使用参考).
从高层次的角度来看,这被认为是最佳做法吗?
非常感谢
许多数据库实现了 no-delete
类集合,为每个文档实现了一个 delete/active
标志。
例如,Employees
集合将变为:
Employees
--> _id: _id
--> FirstName: string
--> Surname: string
--> Email: string
--> Active: boolean
通过这种方式,您可以跟踪已删除的员工数据,并在您有数据库大小限制的情况下防止文档重复。
PS:如今,如果用户要求删除,您可以解决保留用户数据的问题 (RGPD)
编辑:如果 Employees
文档已 更新 并且您想 保留员工的名字、姓名、邮件、等等,当时他制作了 Comment
.
在评论集合中复制员工信息确实是个坏主意。
当需要更改员工信息时,也需要在评论中更新。
您有几个选择:
1-) 在 Employee 模式中嵌入评论:
在此方法中,我们没有单独的 Comments 集合。
如果你不需要独立查询评论,这个方法很有意义。
这样我们就可以在一个数据库访问中访问用户和 his/her 评论,而无需任何连接(填充或查找)。
这个模式可以是这样的:
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 参考:
在这个方法中,我们在 Employee 模式中保留评论的引用。
如果您不需要通过评论访问员工,这可以是一个选项。
员工架构:
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);
评论架构:
const mongoose = require("mongoose");
const commentSchema = new mongoose.Schema({
commentDate: Date,
comment: String
});
module.exports = mongoose.model("Comment", commentSchema);
3-) Child 引用
在这种方法中,我们在评论中保留对员工的引用。
因此,如果您需要访问员工的评论,我们需要使用 mongoose 的 Populate Virtual 功能。因为在员工模式中我们没有对评论的引用。
员工架构:
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);
评论架构:
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-) parent 和 child 均引用:
使用此方法,可以 select 来自员工的评论,以及来自评论的员工。但是这里我们有某种数据重复,而且当评论被删除时,它需要在两个集合中完成。
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);
评论架构:
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);
我很好奇在 Mongo 中表现这种情况的最佳方式。我有自己的想法,但我很好奇一般的 consensus/best 实践究竟是什么。
假设我有两个 collections:-
Employees
--> _id
--> FirstName
--> Surname
--> Email
Comments
--> _id
--> PersonReference
--> CommentDate
--> Comment
现在想象一下,员工可以来来去去,'Employees' collection 总是 up-to-date。但是,如果员工发表过评论,则必须提供评论的完整信息,包括评论者。
我建议解决这个问题的方法是组织这样的结构:-
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 }
所以基本上,我会有一个 'Active Employees' 的列表,并且在发表评论时,我会将员工信息复制到评论 collection 文档中(而不是使用参考).
从高层次的角度来看,这被认为是最佳做法吗?
非常感谢
许多数据库实现了 no-delete
类集合,为每个文档实现了一个 delete/active
标志。
例如,Employees
集合将变为:
Employees
--> _id: _id
--> FirstName: string
--> Surname: string
--> Email: string
--> Active: boolean
通过这种方式,您可以跟踪已删除的员工数据,并在您有数据库大小限制的情况下防止文档重复。
PS:如今,如果用户要求删除,您可以解决保留用户数据的问题 (RGPD)
编辑:如果 Employees
文档已 更新 并且您想 保留员工的名字、姓名、邮件、等等,当时他制作了 Comment
.
在评论集合中复制员工信息确实是个坏主意。 当需要更改员工信息时,也需要在评论中更新。
您有几个选择:
1-) 在 Employee 模式中嵌入评论:
在此方法中,我们没有单独的 Comments 集合。
如果你不需要独立查询评论,这个方法很有意义。 这样我们就可以在一个数据库访问中访问用户和 his/her 评论,而无需任何连接(填充或查找)。
这个模式可以是这样的:
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 参考:
在这个方法中,我们在 Employee 模式中保留评论的引用。 如果您不需要通过评论访问员工,这可以是一个选项。
员工架构:
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);
评论架构:
const mongoose = require("mongoose");
const commentSchema = new mongoose.Schema({
commentDate: Date,
comment: String
});
module.exports = mongoose.model("Comment", commentSchema);
3-) Child 引用
在这种方法中,我们在评论中保留对员工的引用。 因此,如果您需要访问员工的评论,我们需要使用 mongoose 的 Populate Virtual 功能。因为在员工模式中我们没有对评论的引用。
员工架构:
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);
评论架构:
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-) parent 和 child 均引用:
使用此方法,可以 select 来自员工的评论,以及来自评论的员工。但是这里我们有某种数据重复,而且当评论被删除时,它需要在两个集合中完成。
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);
评论架构:
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);