我需要基于userId聚合两个集合,但无法管理它

问题描述 投票:0回答:2

我想汇总下面的集合(评论和帐户),但无法正确管理,因此我需要问你们。

当前评论集写在下面

{
  lawyerId: { type: mongoose.Schema.Types.ObjectId },
  reviews: [
    {
      userId: { type: mongoose.Schema.Types.ObjectId, unique: true },
      message: { type: String },
      rate: { type: Number },
      createdAt: { type: Date, default: Date.now },
    },
  ],
}

如果您推荐评论集可以像这样重构

{
  lawyerId: { type: mongoose.Schema.Types.ObjectId },
  userId: { type: mongoose.Schema.Types.ObjectId },
  message: { type: String },
  rate: { type: Number },
  createdAt: { type: Date, default: Date.now },
}

帐户收集

  {
    _id: { type: mongoose.Schema.Types.ObjectId} 
    email: { type: String, unique: true },
    firstName: { type: String },
    lastName: { type: String },
  },

获取评论的预期结果

{
 averageRate: 3.2,
 reviews: [
 {
  firstName: 'Jack',
  lastName: 'Harden',
  message: 'I dont like it',
  rate: 2, 
  createdAt: '2020-01-01T14:58:23.330+00:00'
 },
 {
  firstName: 'Takeshi',
  lastName: 'San',
  message: 'Thats nice',
  rate: 5, 
  createdAt: '2020-03-02T10:45:10.120+00:00'
 }
],
}
node.js mongodb mongoose database-schema
2个回答
0
投票

您应该可以使用aggregation来实现。

您可以查看实时demo here,使您可以运行此查询。

查询:

// Assuming we are searching for an lawyerId of 3

db.review.aggregate([
  {
    $match: {
      lawyerId: 3
    }
  },
  {
    $lookup: {
      from: "account",
      localField: "userId",
      foreignField: "_id",
      as: "user"
    }
  },
  {
    $unwind: "$user"
  },
  {
    $group: {
      _id: "$lawyerId",
      averageRate: {
        $avg: "$rate"
      },
      reviews: {
        $push: {
          createdAt: "$createdAt",
          firstName: "$user.firstName",
          lastName: "$user.lastName",
          message: "$message",
          rate: "$rate"
        }
      }
    }
  },
  {                    //   *******************************************
    $project: {        //   *******************************************
      _id: 0,          //   If you comment out/remove all of these lines
      averageRate: 1,  //   then the return also contains the 'lawyerId',
      reviews: 1       //   as '_id', which I would find useful...
    }                  //   *******************************************
  }                    //   *******************************************
])

结果:

来自上面的查询,使用来自上面的数据集,产生以下结果:

[
  {
    "averageRate": 3.25,
    "reviews": [
      {
        "createdAt": ISODate("2015-02-28T00:00:00Z"),
        "firstName": "First",
        "lastName": "Uno",
        "message": "Message meh",
        "rate": 3
      },
      {
        "createdAt": ISODate("2015-02-28T00:00:00Z"),
        "firstName": "Second",
        "lastName": "Dos",
        "message": "Message blah",
        "rate": 4
      },
      {
        "createdAt": ISODate("2015-02-28T00:00:00Z"),
        "firstName": "First",
        "lastName": "Uno",
        "message": "Message foo",
        "rate": 4
      },
      {
        "createdAt": ISODate("2015-02-28T00:00:00Z"),
        "firstName": "Third",
        "lastName": "Tres",
        "message": "Message bar",
        "rate": 2
      }
    ]
  }
]

数据集:

Mongo Playground中,您可以构建具有多个集合的数据库,这说明了数据结构:

db={             // <---- Database 'db'
  "account": [   // <---- Collection 'account'
    {
      _id: 21,
      email: "[email protected]",
      firstName: "First",
      lastName: "Uno"
    },
    {
      _id: 22,
      email: "[email protected]",
      firstName: "Second",
      lastName: "Dos"
    },
    {
      _id: 23,
      email: "[email protected]",
      firstName: "Third",
      lastName: "Tres"
    }
  ],
  "review": [    // <---- Collection 'review'
    {
      lawyerId: 3,
      userId: 21,
      message: "Message meh",
      rate: 3,
      createdAt: ISODate("2015-02-28T00:00:00Z")
    },
    {
      lawyerId: 3,
      userId: 22,
      message: "Message blah",
      rate: 4,
      createdAt: ISODate("2015-02-28T00:00:00Z")
    },
    {
      lawyerId: 3,
      userId: 21,
      message: "Message foo",
      rate: 4,
      createdAt: ISODate("2015-02-28T00:00:00Z")
    },
    {
      lawyerId: 3,
      userId: 23,
      message: "Message bar",
      rate: 2,
      createdAt: ISODate("2015-02-28T00:00:00Z")
    }
  ]
}

0
投票

您可以尝试使用此管道从评论集中获取所有评论:

db.reviews.aggregate([
  {
    $lookup: {
      from: "accounts",
      localField: "userId",
      foreignField: "_id",
      as: "user"
    }
  },
  {
    $unwind: "$user"
  },
  {
    $addFields: {
      "firstName": "$user.firstName",
      "lastName": "$user.lastName"
    }
  },
  {
    $group: {
      "_id": null,
      "average_rate": {
        $avg: "$rate"
      },
      "reviews": {
        $push: "$$ROOT"
      }
    }
  },
  {
    $unset: [
      "_id",
      "reviews._id",
      "reviews.user",
      "reviews.userId",
      "reviews.lawyerId"
    ]
  }
])

结果:

[
  {
    "average_rate": 3.5,
    "reviews": [
      {
        "createdAt": "Some Review Date",
        "firstName": "Jack",
        "lastName": "Harden",
        "message": "I dont like it",
        "rate": 2
      },
      {
        "createdAt": "Some Review Date",
        "firstName": "Takeshi",
        "lastName": "San",
        "message": "That's nice",
        "rate": 5
      }
    ]
  }
]

Demo here

© www.soinside.com 2019 - 2024. All rights reserved.