Как найти поле в массиве вложенных документов в пн goose? - PullRequest
0 голосов
/ 12 апреля 2020

У меня есть массив объектов обзора, подобных этому:

   "reviews": {
        "author": "5e9167c5303a530023bcae42",
        "rate": 5,
        "spoiler": false,
        "content": "This is a comment This is a comment This is a comment.",
        "createdAt": "2020-04-12T16:08:34.966Z",
        "updatedAt": "2020-04-12T16:08:34.966Z"
    },

Я хочу добиться, чтобы найти поле author и получить пользовательские данные, но проблема в том, что поиск, который я пытаюсь использовать, только возвращает мне:

Код:

 .lookup({
    from: 'users',
    localField: 'reviews.author',
    foreignField: '_id',
    as: 'reviews.author',
  })

Ответ:

Response of api

Есть ли способ получить данные автора в этом поле? Вот где идентификатор автора.

Ответы [ 3 ]

1 голос
/ 12 апреля 2020

Попробуйте выполнить приведенный ниже запрос к вашей базе данных:

db.reviews.aggregate([
  /** unwind in general is not needed for `$lookup` for if you wanted to match lookup result with specific elem in array is needed */
  {
    $unwind: { path: "$reviews", preserveNullAndEmptyArrays: true },
  },
  {
    $lookup: {
      from: "users",
      localField: "reviews.author",
      foreignField: "_id",
      as: "author", // Pull lookup result into 'author' field
    },
  },
  /** Update 'reviews.author' field in 'reviews' object by checking if   'author' field got a match from 'users' collection.
   * If Yes - As lookup returns an array get first elem & assign(As there will be only one element returned -uniques),
   * If No - keep 'reviews.author' as is */
  {
    $addFields: {
      "reviews.author": {
        $cond: [
          { $ne: ["$author", []] },
          { $arrayElemAt: ["$author", 0] },
          "$reviews.author",
        ],
      },
    },
  },
  /** Group back the documents based on '_id' field & push back all individual 'reviews' objects to 'reviews' array */
  {
    $group: {
      _id: "$_id",
      reviews: { $push: "$reviews" },
    },
  },
]);

Тест: MongoDB-Playground

Примечание: На всякий случай, если у вас есть другие поля в документе наряду с reviews, которые должны быть сохранены при выводе, тогда начиная с $group используйте следующие этапы:

  {
    $group: {
      _id: "$_id",
      data: {
        $first: "$$ROOT"
      },
      reviews: {
        $push: "$reviews"
      }
    }
  },
  {
    $addFields: {
      "data.reviews": "$reviews"
    }
  },
  {
    $project: {
      "data.author": 0
    }
  },
  {
    $replaceRoot: {
      newRoot: "$data"
    }
  }

Test: MongoDB-Playground

Примечание: Старайтесь, чтобы запросы выполнялись для меньших наборов данных, возможно, добавив $match в качестве первого этапа для фильтрации документов и также имейте правильные индексы.

0 голосов
/ 12 апреля 2020

Вы можете следовать этому коду

$lookup:{
            from:'users',
            localField:'reviews.author',
            foreignField:'_id',
            as:'reviews.author'
        }
**OR**

> When You find the doc then use populate
> reviews.find().populate("author")


0 голосов
/ 12 апреля 2020

Вы должны использовать populate('author') метод mon goose при запросе к серверу, который получает идентификатор этого автора и добавляет пользовательские данные к ответу mon goose и не забудьте установить свою схему в Для того, чтобы эти две коллекции были связаны в вашей схеме обзора, вы должны добавить ссылку на схему, в которой автор сохранен автором author: {type: Schema.Types.ObjectId, ref: 'users'},

...