Операция запроса Монго для сопоставления двух элементов в одном и том же индексе - PullRequest
1 голос
/ 19 июня 2019

Объем проекта : я делаю новостную ленту, как Facebook. И у меня есть функция кнопки «Мне нравится», которая при нажатии добавляет сообщение в элемент публикации.

Проблема Допустим, у меня есть два поста, пост А и пост Б.

Если мне нравится пост A, и мне нравится снова, тогда мой сервер возвращает сообщение «Пост уже понравился пользователю», хорошо, это работает.

Однако, если мне нравится пост B, то сервер возвращает то же самое сообщение «Пост уже понравился пользователю»

Запрос:

Feed.findOne({
      owner: req.body.authorId,
      $and: [
        {
          "posts.likes.likeList": {
            $elemMatch: { user: req.user._id }
          }
        },
        { posts: { $elemMatch: { _id: req.body.postId } } }
      ]
    }).then(checkedFeed => {
      if (checkedFeed) {
        return res.status(400).json({ Error: "User has already liked post" });
      }

Что я думаю, проблема в Когда пользователю нравится пост B, а пост A нравится, оператор $and сопоставляет req.user._id с posts.likes.likeList поста A в первом индексе массив $and. Затем он соответствует _id из posts во втором индексе массива $and. А затем возвращает весь канал как совпадение.

Итак, если я прав в этом отношении, как мне написать запрос, который сопоставляет идентификатор записи (второй индекс массива $and) со списком пользователей post.likes.likeList?

Схема

{
  owner: {
    type: Schema.Types.ObjectId,
    ref: "userType"
  },
  posts: [
    {
      likes: {
        totalLikes: { type: Number, default: 0 },
        likeList: [
          {
            user: { type: Schema.Types.ObjectId, ref: "User" },
            avatar: { type: String },
            name: { type: String },
            date: {
              type: Date,
              default: Date.now
            }
          }
        ]
      }
});

Данные испытаний *

    {

//POST B <-------
        "_id" : ObjectId("5d0a61bc5b835b2428289c1b"),
        "owner" : ObjectId("5c9bf6eb1da18b038ca660b8"),
        "posts" : [ 
            {
                "likes" : {
                    "totalLikes" : 0,
                    "likeList" : []
                },
                "_id" : ObjectId("5d0a61bc5b835b2428289c1c"),
                "postBody" : "Test text only",
                "author" : {
                    "userType" : "User",
                    "user" : ObjectId("5c9bf6eb1da18b038ca660b8"),
                    "name" : "Amari DeFrance",
                    "avatar" : "https://stemuli.blob.core.windows.net/stemuli/profile-picture-e1367a7a-41c2-4ab4-9cb5-621d2008260f.jpg"
                }
            }, 
            {
//Post A <------
                "likes" : {
                    "totalLikes" : 1,
                    "likeList" : [ 
                        {
                            "_id" : ObjectId("5d0a66efbac13b4ff8b3b1c8"),
                            "user" : ObjectId("5c9bf6eb1da18b038ca660b8"),
                            "avatar" : "https://stemuli.blob.core.windows.net/stemuli/profile-picture-e1367a7a-41c2-4ab4-9cb5-621d2008260f.jpg",
                            "name" : "Amari DeFrance",
                            "date" : ISODate("2019-06-19T16:46:39.177Z")
                        }
                    ]
                },
                "postBody" : "Test photo",
                "author" : {
                    "userType" : "User",
                    "user" : ObjectId("5c9bf6eb1da18b038ca660b8"),
                    "name" : "Amari DeFrance",
                    "avatar" : "https://stemuli.blob.core.windows.net/stemuli/profile-picture-e1367a7a-41c2-4ab4-9cb5-621d2008260f.jpg"
                },
                "date" : ISODate("2019-06-19T16:25:26.123Z")
            }
        ],
        "__v" : 3
    }

Новый запрос за предложенный ответ

  Feed.aggregate([
      {
        $match: {
          $expr: {
            $and: [
              {
                $eq: ["$owner", req.body.authorId]
              },
              {
                $anyElementTrue: {
                  $map: {
                    input: "$posts",
                    in: {
                      $and: [
                        {
                          $eq: ["$$this._id", req.body.postId]
                        },
                        {
                          $anyElementTrue: {
                            $map: {
                              input: "$$this.likes.likeList",
                              as: "like",
                              in: {
                                $eq: ["$$like.user", req.user._id]
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    ]).then(checkedFeed => {
      if (checkedFeed.length !== 0) {
        return res.status(400).json({ Error: "User has already liked post" });
      }

тестовый запрос MongoDB с постом B, которому понравился пост пользователя

1 Ответ

1 голос
/ 19 июня 2019

Вы можете использовать $ map для преобразования likeList в массив логических значений.Затем вы можете использовать $ anyElementTrue , чтобы проверить, принадлежит ли какой-либо объект тому или иному пользователю.Затем вам нужно проделать тот же трюк для posts (внешний массив), объединяя оба условия с $and, и вы получите желаемые результаты, попробуйте:

Feed.aggregate([
    {
        $match: {
            $expr: {
                $and: [
                    { $eq: [ "$owner", req.body.authorId ] },
                    {
                        $anyElementTrue: {
                            $map: {
                                input: "$posts",
                                in: {
                                    $and: [
                                        { $eq: [ "$$this._id", req.body.postId ] },
                                        {
                                            $anyElementTrue: {
                                                $map: {
                                                    input: "$$this.likes.likeList",
                                                    as: "like",
                                                    in: { $eq: [ "$$like.user", req.user._id ] }
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    }
                ]
            }
        }
    }
])

Рабочий пример

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...