Мне нужно объединить две коллекции на основе идентификаторов пользователей, но я не смог управлять ими - PullRequest
0 голосов
/ 02 марта 2020

Я хочу объединить коллекции ( Review и Account ) ниже, но не смог правильно с ними справиться, поэтому мне нужно было спросить вас, ребята.

Текущая Review Collection написано ниже

{
  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'
 }
],
}

Ответы [ 2 ]

0 голосов
/ 02 марта 2020

Вы можете попробовать этот конвейер, чтобы получить все отзывы из коллекции обзоров:

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
      }
    ]
  }
]

Демо здесь

0 голосов
/ 02 марта 2020

Этого можно добиться, используя агрегацию .

Здесь вы можете посмотреть демонстрацию , которая позволяет выполнить этот запрос.

Запрос:

// 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
      }
    ]
  }
]

Набор данных:

В Пн go Детская площадка , вы можете создавать базы данных с несколькими коллекциями, это объясняет структуру данных:

db={             // <---- Database 'db'
  "account": [   // <---- Collection 'account'
    {
      _id: 21,
      email: "first.uno@gmail.com",
      firstName: "First",
      lastName: "Uno"
    },
    {
      _id: 22,
      email: "second.dos@yahoo.com",
      firstName: "Second",
      lastName: "Dos"
    },
    {
      _id: 23,
      email: "third.tres@hotmail.com",
      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")
    }
  ]
}
...