在猫鼬中为朋友模式建模?
Posted
技术标签:
【中文标题】在猫鼬中为朋友模式建模?【英文标题】:Modelling for friends schema in mongoose? 【发布时间】:2018-10-26 01:20:30 【问题描述】:当我在其他用户的个人资料上时,如何为我的猫鼬模式建模以获取这三个按钮?
-
加好友
已请求
朋友
我的用户架构
const schema = new Mongoose.Schema(
firstName: type: String, default: '', trim: true ,
lastName: type: String, default: '', trim: true ,
, timestamps: true )
我找不到正确的建模...并且还请在建模后建议聚合...
【问题讨论】:
这个问题的答案应该对你有帮助:***.com/questions/6183147/… 假设您有用户 A 和用户 B。当用户 A 在用户 B 的好友列表中并且用户 B 在用户 A 的列表中时,您可以定义一个好友。待定可能是当用户 A 请求成为用户 B 的朋友(因此用户 B 在用户 A 的列表中),但用户 B 没有接受(意味着用户 A 不在用户 B 的列表中)。我知道这很罗嗦,但我希望这会有所帮助。 【参考方案1】:所以最后我做到了,我认为这可能是使用 mongodb 和 mongoose 的最佳方法
1.为用户创建模型。
var Schema = mongoose.Schema
const usersSchema = new Schema(
firstName: type: String, required: true ,
lastName: type: String, required: true ,
friends: [ type: Schema.Types.ObjectId, ref: 'Friends']
, timestamps: true)
module.exports = mongoose.model('Users', usersSchema)
2. 为具有接受、拒绝、待处理和请求的枚举的朋友创建一个模型。
const friendsSchema = new Schema(
requester: type: Schema.Types.ObjectId, ref: 'Users',
recipient: type: Schema.Types.ObjectId, ref: 'Users',
status:
type: Number,
enums: [
0, //'add friend',
1, //'requested',
2, //'pending',
3, //'friends'
]
, timestamps: true)
module.exports = mongoose.model('Friends', friendsSchema)
3. 现在 api 调用 --> 假设我们有两个用户 UserA 和 UserB... 所以当 UserA 请求 UserB 成为朋友时,我们会做两个 文档,以便用户 A 可以看到请求,用户 B 可以看到待处理 同时我们将这些文档的_id推送到用户的 朋友
const docA = await Friend.findOneAndUpdate(
requester: UserA, recipient: UserB ,
$set: status: 1 ,
upsert: true, new: true
)
const docB = await Friend.findOneAndUpdate(
recipient: UserA, requester: UserB ,
$set: status: 2 ,
upsert: true, new: true
)
const updateUserA = await User.findOneAndUpdate(
_id: UserA ,
$push: friends: docA._id
)
const updateUserB = await User.findOneAndUpdate(
_id: UserB ,
$push: friends: docB._id
)
4.如果UserB接受请求
Friend.findOneAndUpdate(
requester: UserA, recipient: UserB ,
$set: status: 3
)
Friend.findOneAndUpdate(
recipient: UserA requester: UserB ,
$set: status: 3
)
5.如果UserB拒绝请求
const docA = await Friend.findOneAndRemove(
requester: UserA, recipient: UserB
)
const docB = await Friend.findOneAndRemove(
recipient: UserA, requester: UserB
)
const updateUserA = await User.findOneAndUpdate(
_id: UserA ,
$pull: friends: docA._id
)
const updateUserB = await User.findOneAndUpdate(
_id: UserB ,
$pull: friends: docB._id
)
6.获取所有好友并检查登录用户是否为该用户的好友
User.aggregate([
"$lookup":
"from": Friend.collection.name,
"let": "friends": "$friends" ,
"pipeline": [
"$match":
"recipient": mongoose.Types.ObjectId("5afaab572c4ec049aeb0bcba"),
"$expr": "$in": [ "$_id", "$$friends" ]
,
"$project": "status": 1
],
"as": "friends"
,
"$addFields":
"friendsStatus":
"$ifNull": [ "$min": "$friends.status" , 0 ]
])
【讨论】:
你能解释一下阻塞,解除阻塞吗? 您好,很抱歉寻求帮助,但 ObjectId.... 引用了当前登录的用户或您实际查看的配置文件? (也就是不属于您的个人资料)? 如果数组中有成千上万的朋友,这会是一个问题吗?这会导致 mongodb 出现问题吗? 不错的实现,但为什么你有一个添加朋友的枚举?我认为如果两个用户之间没有友谊,可以只推荐这个,不是吗? @OhadChaet 只是为了更清楚地说明问题。但这取决于你。:-)【参考方案2】:这个问题有点晚了,但这是我的解决方案:
-
为用户创建“自我参照”模型:
const Schema = mongoose.Schema;
// Create Schema
const UserSchema = new Schema(
firstName:
type: String,
required: true
,
lastName:
type: String,
required: true
,
friends: [
user:
type: Schema.Types.ObjectId,
ref: 'users',
,
status: Number,
enums: [
0, //'add friend',
1, //'requested',
2, //'pending',
3, //'friends'
]
]
)
现在,如果您想查询好友,您可以使用聚合函数并匹配好友列表中的所有用户:
exports.getFriends = async (req, res) =>
let id = req.params
let user = await User.aggregate([
"$match": "_id": ObjectId(id) ,
"$lookup":
"from": User.collection.name,
"let": "friends": "$friends" ,
"pipeline": [
"$match":
"friends.status": 1,
,
"$project":
"name": 1,
"email": 1,
"avatar": 1
],
"as": "friends"
,
])
res.json(
user
)
这种方法的优点之一是您可以进行较小的查询,而不是创建一个友谊连接表,这些查询的成本可能会低一些。而且它对我来说似乎更直观。但是我对 mongo 还很陌生,所以我不太确定最佳实践是什么。
【讨论】:
以上是关于在猫鼬中为朋友模式建模?的主要内容,如果未能解决你的问题,请参考以下文章