Заполните поле вложенного массива после агрегации - PullRequest
1 голос
/ 03 мая 2020

Я хотел бы заполнить ссылочную модель после агрегации. Пока у меня есть это решение. Я хотел бы заполнить пользовательский объект. У него есть имя, адрес электронной почты, поля телефона. Агрегация работает отлично, я получаю желаемый результат, но поле пользователя не заполняется. Я прочитал так много похожих решений, но, к сожалению, ни одно из них не сработало.

 exports.getResultToCompetition = asyncHandler(async (req, res, next) => {
  let competitionId = await Competition.findById(req.params.competitionId).select("_id");

  const result = await Result.aggregate([
    {
      // $match: { competition: mongoose.Types.ObjectId("competitionId") },
      $match: { competition: mongoose.Types.ObjectId(competitionId._id) },
    },
    {
      $project: {
        points: 1,
        kilogramms: 1,
        sector: 1,
        user: 1,
        competition: 1,
        place: 1,
      },
    },

    {
      $group: {
        _id: "$sector",
        res: { $push: "$$ROOT" },
      },
    },
    {
      $sort: {
        kilogramms: -1,
      },
    },
  ]);
  await Result.populate(result, { path: "user", select: "email name avatar flag" });

  res.status(200).json({ success: true, data: result });
});

То, что я тоже пробовал, но не работает.

await Result.populate(result, {
    path: "result",
    populate: {
      path: "res",
      model: "Result",
      populate: {
        path: "user",
        model: "User",
        select: "email name avatar flag",
      },
    },
  });

Это то, что я получаю в Почтальоне.

{
    "success": true,
    "data": [
        {
            "_id": "A",
            "res": [
                {
                    "_id": "5eaeab6b2b9f246693a65659",
                    "points": 14,
                    "kilogramms": 14,
                    "place": 14,
                    "sector": "A",
                    "competition": "5eaeaa5448580765da33165a",
                 {
                    "_id": "5eaec018784ea96aa7daeebe",
                    "points": 23,
                    "kilogramms": 23,
                    "place": 12,
                    "sector": "A",
                    "competition": "5eaeaa5448580765da33165a",
           //Expected output includes the user object
                    "user": {
                      "_id": "5eaebf3471aab66a84ae01a4",
                       "name": "John Mayer",
                       "email": "johnmayer@gmail.com",
                       "phone": "123456789"
               }
            },
                },
                {
                    "_id": "5eaec018784ea96aa7daeebe",
                    "points": 23,
                    "kilogramms": 23,
                    "place": 12,
                    "sector": "A",
                    "competition": "5eaeaa5448580765da33165a",
                    "user": "5eaebf3471aab66a84ae01a4"
                },
                {
                    "_id": "5eaec028784ea96aa7daeebf",
                    "points": 12,
                    "kilogramms": 12,
                    "place": 14,
                    "sector": "A",
                    "competition": "5eaeaa5448580765da33165a",
                    "user": "5eaebf7f784ea96aa7daeeba"
                }
            ]
        },
        {
            "_id": "B",
            "res": [
                {
                    "_id": "5eaec03c784ea96aa7daeec0",
                    "points": 30,
                    "kilogramms": 34,
                    "place": 1,
                    "sector": "B",
                    "competition": "5eaeaa5448580765da33165a",
                    "user": "5eaebfa7784ea96aa7daeebb"
                },
                {
                    "_id": "5eaec04c784ea96aa7daeec1",
                    "points": 21,
                    "kilogramms": 20,
                    "place": 2,
                    "sector": "B",
                    "competition": "5eaeaa5448580765da33165a",
                    "user": "5eaebfd4784ea96aa7daeebc"
                },
                {
                    "_id": "5eaec05a784ea96aa7daeec2",
                    "points": 13,
                    "kilogramms": 13,
                    "place": 3,
                    "sector": "B",
                    "competition": "5eaeaa5448580765da33165a",
                    "user": "5eaebff5784ea96aa7daeebd"
                }
            ]
        }
    ]
}

1 Ответ

1 голос
/ 03 мая 2020

Во-первых, вам не нужна следующая строка:

let competitionId = await Competition.findById(req.params.competitionId).select("_id");

Также обратите внимание, что вам нужно отсортировать группу kilogramms перед $, иначе это не даст никакого эффекта.

Наконец, вы можете получить информацию о пользователе, используя $ lookup , например:

exports.getResultToCompetition = asyncHandler(async (req, res, next) => {
  const data = await Result.aggregate([
    {
      $match: { competition: mongoose.Types.ObjectId(req.params.competitionId) },
    },
    {
      $project: {
        points: 1,
        kilogramms: 1,
        sector: 1,
        user: 1,
        competition: 1,
        place: 1,
      },
    },
    {
      $sort: {
        kilogramms: -1,
      },
    },
    {
      $lookup: {
        from: "users", // must be the PHYSICAL name of the collection
        localField: "user",
        foreignField: "_id",
        as: "user",
      },
    },
    {
      $addFields: {
        user: {
          $arrayElemAt: ["$user", 0],
        },
      },
    },
    {
      $group: {
        _id: "$sector",
        res: {
          $push: "$$ROOT",
        },
      },
    },
  ]);

  res.status(200).json({ success: true, data });
});

Детская площадка

Вывод будет выглядеть следующим образом:

[
  {
    "_id": "A",
    "res": [
      {
        "_id": "5eaec018784ea96aa7daeebe",
        "competition": "5eaeaa5448580765da33165a",
        "kilogramms": 23,
        "place": 12,
        "points": 23,
        "sector": "A",
        "user": {
          "_id": "5eaebf3471aab66a84ae01a4",
          "email": "user2_email",
          "name": "User2",
          "phone": "user2_phone"
        }
      },
      {
        "_id": "5eaeab6b2b9f246693a65659",
        "competition": "5eaeaa5448580765da33165a",
        "kilogramms": 14,
        "place": 14,
        "points": 14,
        "sector": "A",
        "user": {
          "_id": "5ead24956ee84737c5910d06",
          "email": "user1_email",
          "name": "User1",
          "phone": "user1_phone"
        }
      },
      {
        "_id": "5eaec028784ea96aa7daeebf",
        "competition": "5eaeaa5448580765da33165a",
        "kilogramms": 12,
        "place": 14,
        "points": 12,
        "sector": "A",
        "user": {
          "_id": "5eaebf7f784ea96aa7daeeba",
          "email": "user3_email",
          "name": "User3",
          "phone": "user3_phone"
        }
      }
    ]
  },
  {
    "_id": "B",
    "res": [
      {
        "_id": "5eaec03c784ea96aa7daeec0",
        "competition": "5eaeaa5448580765da33165a",
        "kilogramms": 34,
        "place": 1,
        "points": 30,
        "sector": "B",
        "user": {
          "_id": "5eaebfa7784ea96aa7daeebb",
          "email": "user4_email",
          "name": "User4",
          "phone": "user4_phone"
        }
      },
      {
        "_id": "5eaec04c784ea96aa7daeec1",
        "competition": "5eaeaa5448580765da33165a",
        "kilogramms": 20,
        "place": 2,
        "points": 21,
        "sector": "B",
        "user": {
          "_id": "5eaebfd4784ea96aa7daeebc",
          "email": "user5_email",
          "name": "User5",
          "phone": "user1_phone"
        }
      },
      {
        "_id": "5eaec05a784ea96aa7daeec2",
        "competition": "5eaeaa5448580765da33165a",
        "kilogramms": 13,
        "place": 3,
        "points": 13,
        "sector": "B",
        "user": {
          "_id": "5eaebff5784ea96aa7daeebd",
          "email": "user6_email",
          "name": "User6",
          "phone": "user6_phone"
        }
      }
    ]
  }
]
...