【问题标题】:Mongo query operation for matching two elements within same index用于匹配同一索引内的两个元素的 Mongo 查询操作
【发布时间】:2019-06-20 02:36:12
【问题描述】:

项目范围:我正在制作新闻源,例如 Facebook。而且我有一个点赞按钮功能,点击后会为帖子添加点赞。

问题假设我有两个帖子,帖子 A 和帖子 B。

如果我喜欢帖子 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 与第一个索引中帖子 A 的 posts.likes.likeList 匹配$and 数组。然后,它匹配posts_id$and 数组的第二个索引中。然后将整个提要作为匹配项返回。

那么,如果我在这方面是正确的,我该如何编写一个查询来匹配 post id($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 query test with post B having liked post from the user

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    您可以使用$maplikeList 转换为布尔值数组。然后您可以使用$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 ] }
                                                    }
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        }
    ])
    

    Working example

    【讨论】:

    • 我正在测试它,它返回相同的响应。我将暂时查看其中一些 mongodb 聚合运算符的文档。我从来没有真正使用过它们。非常感谢你,你让我走上了我想要的正确道路。
    • @user10204157 你能比较一下mongoplayground.net/p/uL7haNSdfc8(你的查询)和mongoplayground.net/p/dej5H2fIhg7(我的解决方案)吗?
    • @user10204157 太棒了,请在这里链接,我稍后会尝试看看
    • @user10204157 这是一个示例,该查询返回文档,因为 postId 和 userId 属于同一个帖子:mongoplayground.net/p/Md6BqGGE3Ex
    • 谢谢,我不知道为什么即使添加了值本身,我仍然没有收到任何文件。在获得所需的提要后,我编写了自己的映射函数。你给了我很多关于如何使用聚合的见解,再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多