Как использовать несколько $ lookup с массивами объектов

#javascript #mongodb #aggregation-framework #aggregate

#javascript #mongodb #агрегация-фреймворк #агрегировать

Вопрос:

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

почтовый индекс:

 {
    _id: ObjectId("5fce0e137ff7401634bad2ac")
    address: "new york"
    description: "this is a great city"
    image: "images.4644859674390589-gikiguk.jpg"
    userId: "5fcdcd8487e37216bc82171b"
}
 

номер пользователя:

 {
    _id: ObjectId("5fcdcd8487e37216bc82171b")
    name: "jack"
    profile: {image: "images.4644859674390589-dofowfg.jpg", description: "be happy dude"}
    email: "test@test.com"
    password: "2a$12$gzRrY83QAjwLhdyvn3JQ2OcMj3XG65.BULva4cZqcuSxDhhMbSXCq"
}
 

Лайки и комментарии col:

 {
    _id: ObjectId("5fce0e191ff7301666kao2xc")
    likes: {quantity: 1, likes: [{isActive: true, userId: "5fcdcd8487c31216cc87886r"}]}
    comments: {quantity: 1, comments: [{userId: "5fcdcd8487c31216cc87886r" , comment: "awesome city"}]}
    postId: "5fce0e137ff7401634bad2ac"
}
 

что я хочу сделать, так это то, что у меня есть идентификатор пользователя (возможно, более одного), по которому я хочу выполнить поиск по всем сообщениям (которые принадлежат пользователю) и получить некоторые данные, posts collection а затем $lookup users collection снова получить некоторые данные о пользователе, и после этого каждое сообщение имеет собственное postId (я преобразовал _id в postId ). с postId помощью я могу $lookup получить likeComments documents и получить некоторые данные о любых сообщениях, но если у сообщения нет никаких лайков или комментариев, все мои запросы, которые я им написал, дают мне пустой массив [] (вообще не данные, а просто пустой массив), но если у сообщения есть хотя бы один лайк и один комментарий, все из моего запроса работает поиск.

то, что я ожидаю, это что-то вроде этого:

     [
      {
        postId: '5fce0e137ff7401634bad2ac',    //from post
        location: 'shiraz', // from post
        description: 'this is a greate city',    // from post
        image: 'images\0.4644859674390589-gikiguk.jpg',    // from post
        userId: '5fcdcd8487e37216bc82171b',    // from user
        name: 'mohammad',    // from user
        profile: 'images\0.6093033055735912-DSC_0002_2.JPG',    // from user
        comments: { quantity: 1, comments: [{userId: "...", name: "...", profile: "...", comment: "..."}] },    // from likesComments and then lookup to users documets to get data about users that wrote comments
        likes: {quantity: 1, [{userId: "...", name: "...", profile: "..."}]}    // from likesCommnets and then lookup to users documets to get data about users that liked the post
      }
    ]
 

запрос:

я знаю, что мой запрос неверен, но я не могу найти, что здесь не так.

 db.collection("posts")
          .aggregate([
            { $match: { userId: { $in: users.map(u => u) } } },
            {
              $project: {
                _id: 0,
                userId: { $toObjectId: "$userId" },
                postId: { $toString: "$_id" },
                location: "$address",
                description: "$description",
                image: "$image"
              }
            },
            {
              $lookup: {
                from: "users",
                localField: "userId",
                foreignField: "_id",
                as: "userInfo"
              }
            },
            { $unwind: "$userInfo" },
            {
              $project: {
                _id: 0,
                postId: 1,
                location: 1,
                description: 1,
                image: 1,
                userId: { $toString: "$userId" },
                name: "$userInfo.name",
                profile: "$userInfo.profile.image"
              }
            },
            {
              $lookup: {
                from: "likes-comments",
                localField: "postId",
                foreignField: "postId",
                as: "likesComments"
              }
            },
            { $unwind: "$likesComments" },
            {
              $project: {
                postId: 1,
                location: 1,
                description: 1,
                image: 1,
                userId: 1,
                name: 1,
                profile: 1,
                likes: {
                  $map: {
                    input: "$likesComments.likes.likes",
                    as: "item",
                    in: {
                      $toObjectId: "$item.userId"
                    }
                  }
                },
                quantity: "$likesComments.comments.quantity",
                comments: {
                  comments: {
                    $map: {
                      input: "$likesComments.comments.comments",
                      as: "item",
                      in: {
                        $toObjectId: "$item.userId"
                      }
                    }
                  }
                }
              }
            },
            {
              $lookup: {
                from: "users",
                localField: "likes",
                foreignField: "_id",
                as: "likes"
              }
            },
            { $unwind: "$likes" },
            {
              $lookup: {
                from: "users",
                localField: "comments.comments",
                foreignField: "_id",
                as: "comments"
              }
            },
            { $unwind: "$comments" },
            { $addFields: { quantity: "$quantity" } },
            {
              $project: {
                _id: 0,
                postId: 1,
                location: 1,
                description: 1,
                image: 1,
                userId: 1,
                name: 1,
                profile: 1,
                likes: [
                  {
                    userId: { $toString: "$likes._id" },
                    name: "$likes.name",
                    profile: "$likes.profile.image"
                  }
                ],
                comments: {
                  quantity: 1,
                  comments: [
                    {
                      userId: { $toString: "$comments._id" },
                      name: "$comments.name",
                      profile: "$comments.profile.image"
                    }
                  ]
                }
              }
            }
          ])
          .toArray();
 

Ответ №1:

В вашем примере есть несколько проблем:

  1. проверьте имена коллекций при поиске $. Существует множество несоответствий с названиями ваших коллекций.
  2. проверьте types и names поля $lookup. Некоторые идентификаторы находятся в строке, в то время как некоторые из них находятся в ObjectId. Это приведет к недопустимому поиску. Возможно, вам потребуется использовать вложенные запросы в $lookup для преобразования типов перед поиском.
  3. Некоторые из ваших идентификаторов объектов содержат не шестнадцатеричные символы (например _id , of likeComments )
  4. проблема с данными в примере; некоторые идентификаторы просто не совпадают. (например likeComments.likes.likes.userId , vs user._id )

Вот ПЕРВАЯ ПОЛОВИНА вашего конвейера с исправлениями части вышеуказанных проблем. Возможно, вы захотите использовать его в качестве ссылки для устранения оставшихся проблем.