Hoo*_*ari 6 database mongoose mongodb node.js graphql
试图解决MongoDB中关系的缺点,这是我在我的数据库中尝试的:
楷模:
uid但_id也可用.产品规格:
每个用户都可以是该团队的成员或该应用程序的独立用户.普通用户可以拥有自己的私有项目和资产.
团队成员可以访问团队所有者认为可以访问的资产和项目.
会员可以创建自己的私人资产和项目.
根据成员的角色,成员还可以与其团队成员共享资产.
成员,根据其角色,可以添加,删除,编辑团队资产,删除或重命名团队,添加或删除团队成员.
成员可以查看团队中与他们共享的资产和项目的列表.
成员可以查看单个资产页面,他们可以根据角色在资产中添加删除项目.
成员可以查看,编辑,添加,删除单个项目,具体取决于他们的角色.
目前的架构:
const teamSchema = new Schema({
uid: {
type: String,
required: true
},
name: {
type: String,
required: true
},
members: {
type: [String]
},
brands: {
type: [String]
}
}, { collection: 'team', timestamps: true });
const memberSchema = new Schema({
uid: {
type: String,
required: true
},
owner: {
type: String,
required: true
},
teamID: {
type: Schema.Types.ObjectId,
required: true
},
acl: {
type: String,
required: true,
enum: ['view', 'copy', 'edit', 'admin', 'owner'],
default: 'view'
},
pending: {
type: Boolean,
default: true
}
}, { collection: 'member', timestamps: true, _id: false });
const assetsSchema = new Schema({
uid: {
type: String,
required: true
},
title: {
type: String,
required: true
},
fonts: [AssetFile],
colors: [Color],
logos: [AssetFile],
images: [AssetFile],
projects: Array,
items: Array,
members: [String]
}, { collection: 'branding', timestamps: true });
const userSchema = new Schema({
uid: {
type: String,
required: true
},
email: {
type: String,
required: true,
lowercase: true,
index: { unique: true },
validate: v => validator.isEmail(v)
},
avatar: String,
files: [FilesSchema],
isAdmin: Boolean,
projectCount: {
type: Number,
default: 0
},
userName: {
type: String,
trim: true
},
userType: {
type: String,
required: true,
default: 'Free User'
},
lastSeenAt: {
type: Date
},
}, { collection: 'user', timestamps: true });
const projectSchema = new Schema({
uid: {
type: String,
required: true
},
objects: Array,
projectTitle: {
type: String,
trim: true,
default: 'Untitled Project'
},
preview: {
type: String
},
folder: {
type: String,
trim: true,
default: null
},
archived: {
type: Boolean,
default: false
},
}, { collection: 'project', timestamps: true });
Run Code Online (Sandbox Code Playgroud)
这些可以在关系数据库中轻松实现,但由于我的应用程序已经超过4万用户,因此转移到另一个数据库并不是一个简单的选择.
这些可以在MongoDB中实现,我应该如何,或者应该停止尝试并转移到另一个数据库?
我已经在使用mongoose,但我也愿意使用本机MongoDB代码(例如聚合,$ lookup等)
编辑:
对我来说,可扩展性的问题不仅仅是学习如何在MongoDB中编写查询,所以这里有我已经拥有的查询:
资产清单:
const personalAssets = await AssetsModel.aggregate([
{ $match: { uid: user.uid } },
{ $project: { _id: 1, uid: 1, title: 1, logos: 1, teamID: 1, acl: 'owner', createdAt: 1, fonts: 1 } },
{ $sort: { createdAt: -1 } }
]);
const sharedAssets = await MemberModel.aggregate([
{
$match: {
$or: [
{ uid: user.uid },
{ owner: user._id }
]
}
},
{ $project: { _id: 0, acl: 1, teamID: 1, owner: 1 } },
{
$lookup: {
from: 'team',
let: { team_id: '$teamID' },
pipeline: [
{
$match: {
$expr: {
$eq: [ '$_id', '$$team_id' ]
}
}
},
{ $project: { _id: 0, assets: 1, teamID: '$$team_id' } }
],
as: 'team'
}
},
{ $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ '$team', 0 ] }, '$$ROOT' ] } } },
{ $project: { assets: 1, acl: 1, teamID: 1, owner: 1 } },
{ $match: { 'assets.0': { $exists: true } } },
{
$lookup: {
from: 'branding',
let: { 'assets': '$assets' },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: [ '$_id', '$$assets' ] },
{ $ne: [ '$uid', user.uid ] }
]
}
}
}
],
as: 'assets'
}
},
{ $unwind: '$assets' },
{
$replaceRoot: {
newRoot: {
$mergeObjects: ['$assets', { acl: '$acl' }, { teamID: '$teamID' }, { owner: '$owner' }]
}
}
},
{
$project: {
assets: 1,
acl: {
$cond: {
if: { $eq: [ user._id, '$owner' ] },
then: 'owner',
else: '$acl'
}
},
_id: 1,
uid: 1,
title: 1,
teamID: 1,
logos: 1,
fonts: 1
}
}
]);
return [...personalAssets, ...sharedAssets];
Run Code Online (Sandbox Code Playgroud)
单一资产:
const personalAsset = await AssetsModel.findOne({ _id, uid: user.uid });
if (brand) asset.acl = 'owner';
const sharedAsset = await MemberModel.aggregate([
{
$match: {
$and: [
{ teamID: mongoose.Types.ObjectId(teamID) },
{
$or: [
{ uid: user.uid },
{ owner: user._id }
]
}
]
}
},
{ $project: { _id: 0, acl: 1, teamID: 1, owner: 1 } },
{
$lookup: {
from: 'team',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: [ '$_id', mongoose.Types.ObjectId(teamID) ] },
{ $in: [ mongoose.Types.ObjectId(_id), '$assets' ] }
]
}
}
},
{ $project: { _id: 0, assets: 1, teamID: teamID } }
],
as: 'team'
}
},
{ $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ '$team', 0 ] }, '$$ROOT' ] } } },
{ $match: { 'assets.0': { $exists: true } } },
{
$lookup: {
from: 'branding',
pipeline: [
{
$match: {
$expr: {
$eq: [ '$_id', mongoose.Types.ObjectId(_id) ]
}
}
}
],
as: 'assets'
}
},
{ $unwind: '$assets' },
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
'$assets',
{
acl: {
$cond: {
if: { $eq: [ user._id, '$owner' ] },
then: 'owner',
else: '$acl'
}
}
},
{ teamID: '$teamID' }
]
}
}
}
]);
brand = sharedAsset[0];
Run Code Online (Sandbox Code Playgroud)
文件夹和项目也是如此.这里的主要挑战是获取资产列表并获取成员ACL(访问控制级别).对单个资产(文件夹和项目)执行此操作更容易.
我的主要问题是如何构建我的架构并以更可扩展的方式查询它们.
| 归档时间: |
|
| 查看次数: |
190 次 |
| 最近记录: |