在检查匹配项的同时使用聚合 Mongoose 查询的结果(Mongoose/Express)

Posted

技术标签:

【中文标题】在检查匹配项的同时使用聚合 Mongoose 查询的结果(Mongoose/Express)【英文标题】:Use Results From Aggregate Mongoose Queries While Also Checking for Matches (Mongoose/Express) 【发布时间】:2021-09-10 14:10:04 【问题描述】:

我有一个用户和帖子集合:

const posts = [
  post_id: "123abc", author_id: "cba321", body: "postdatastuff",
  post_id: "456def", author_id: "fed654", body: "postdatastuff",
  post_id: "789hij", author_id: "fed654", body: "postdatastuff",
  post_id: "101klm", author_id: "mlk101", body: "postdatastuff",
]

const users = [
  user_id: "cba321", liked_posts: ["123abc", "456def"],
  user_id: "fed654", liked_posts: ["789hij", "123abc"],
  user_id: "jih987", liked_posts: ["456def", "123abc", "789hij"],
]

如果我以用户“cba321”的身份登录,并且我想返回用户“fed654”的所有帖子,同时还要检查我是否喜欢他们的每个帖子,我将如何编写 mongoose 聚合查询实现这一目标?

这个聚合函数会返回:

const posts = [
      post_id: "456def", author_id: "fed654", body: "postdatastuff", liked: true,
      post_id: "789hij", author_id: "fed654", body: "postdatastuff", liked: false,
];

目前,我正在写这个没有猫鼬聚合。我的解决方案不仅不起作用,而且效率不高,因为它必须将值返回到服务器并在 2 个单独的进程中处理它们,我希望它是一个 100% 的 mongoose 本机聚合函数。

这是我的尝试:

router.post("path", async (req, res) => 
  const reqUser = await User.findOne( _id: req.body.u_id ).lean(); //gets requesting users user information
  const user = await User.findOne( uName: req.body.uName ).lean(); //gets the url's path userName user information.
  const posts = await Post.find( a_id: user._id ).lean(); //gets all the posts from the previously searched user
  const resData = posts.map((p) => 
    return 
      ...p,
      author_name: user.name, //combines the users name as the author name with each post
      author_uName: user.uName,
      liked: reqUser.likes.indexOf(p._id), //checks to see if the requesting user has liked the post
    ;
  );
  res.status(200).json(resData);
);

这个函数返回类似:

]   
   
     _id: 123abc,
     body: 'testbodytext',
     author_id: 'cba321',
     a_name: 'test',
     a_uName: 'test',
     liked: -1
   
 ]

当您查看显示用户发布的其他用户页面/个人资料以及您是否喜欢他们时,此查询聚合复制了 youtube 或 twitter 的功能。

基本上,此函数从用户集合中获取用户/作者的单个 _id,并使用它在帖子集合中搜索任何匹配的 author_id。然后它将返回所有匹配的帖子,同时检查请求用户是否喜欢每个帖子。

我正在寻找不基于 javascript、promise、异步或瀑布方法的答案。

谢谢!

【问题讨论】:

【参考方案1】:

如果我以用户“cba321”的身份登录,并且我想退回所有 发布用户“fed654”,同时检查我是否喜欢每个 他们的帖子,...

您查询 users 集合并提供两个输入变量 - 登录用户和您喜欢的帖子的作者/用户 - 以获得所需的结果。查询在mongo shell 中运行,返回以下结果:


        "post_id" : "456def",
        "author_id" : "fed654",
        "body" : "postdatastuff",
        "liked" : true

聚合查询:

db.users.aggregate([
   
      $match:  user_id: "cba321"     // <-- signed in user
  ,
   
      $unwind: "$liked_posts" 
  ,
  
      $lookup: 
          from: "posts",
          let:  likedPost: "$liked_posts" ,
          pipeline: [
                $match:  
                      $expr:  
                          $and: [
                               $eq: [ "$post_id", "$$likedPost" ] ,
                               $eq: [ "fed654", "$author_id" ]     // <-- posts for a specified user/author
                          ]
                
          ],
          as: "matched_posts",
      
  ,
   
      $match:  
          $expr:  $gt: [  $size: "$matched_posts" , 0 ]  
       
  ,
  
      $unwind: "$matched_posts"
  ,
   
      $replaceWith: "$matched_posts" 
  ,
   
      $addFields:  
          _id: "$$REMOVE",
          liked: true
       
  ,
])

【讨论】:

以上是关于在检查匹配项的同时使用聚合 Mongoose 查询的结果(Mongoose/Express)的主要内容,如果未能解决你的问题,请参考以下文章

具有 .every() 等效项的 Mongoose 聚合

mongodb 在节点中使用 mongoose 想要在查询中使用 or 和

Mongoose 聚合匹配 objectIds 数组

如何根据现有的 mongoose 查询检查单个文档?

Mongoose,使用 $lookup 的聚合查询返回 null?

Mongoose 使用异步迭代器流式传输聚合查询