在mongoose中为朋友模式建模?

时间:2018-05-16 05:45:37

标签: node.js mongodb mongoose mongodb-query aggregation-framework

当我在其他用户个人资料上时,如何建模我的猫鼬模式以获取这三个按钮?

  1. 添加好友
  2. 请求
  3. 我的用户架构

    const schema = new Mongoose.Schema({
      firstName: { type: String, default: '', trim: true },
      lastName: { type: String, default: '', trim: true },
    }, { timestamps: true })
    

    我找不到正确的建模......还请在建模后建议聚合......

2 个答案:

答案 0 :(得分:5)

所以最后我做到了,我认为这可能是用mongodb做到这一点的最好方法

  

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成为朋友的时候我们做两个   文档,以便UserA可以看到请求和UserB可以看到挂起   同时我们将这些文件的_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": ObjectId("5afaab572c4ec049aeb0bcba"),
        "$expr": { "$in": [ "$_id", "$$friends" ] }
      }},
      { "$project": { "status": 1 } }
    ],
    "as": "friends"
  }},
  { "$addFields": {
    "friendsStatus": {
      "$ifNull": [ { "$min": "$friends.status" }, 0 ]
    }
  }}
])

答案 1 :(得分:0)

这个问题有点晚了,但这是我的解决方法:

  1. 为用户创建“自我引用”模型:
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还是很陌生,所以我不太确定最佳做法是什么。