灵活运用mongodb的操作符

175

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

前言

本文章内容重点是在操作符的使用上,如果要更好的了解具体的概念请移步到 mongodb官网文档

$project

假设有一个作品表

import { ObjectID } from "mongodb";

async function getArtworkByArtworkId(artworkId: string) {
   const res = await artworkRepo.aggregate([
       { $match: { _id: { $eq: new ObjectID(artworkId) } } }, 
    ]).toArray();
}

// 查询结果
[
    {
        _id: "",
        name: "",
        imgUrl: "",
        desc: "",
        authorId: "",
        status: "",
        createTime: "",
    }
]

我现在不想查出那么多字段啊,我只想要这个作品的id和图片,一个方法是拿到结果后取出想要的数据再返回给前端。第二个方法就是,让查询语句来帮我做这件事。如何做呢?这个时候就用到 $project 这个操作符了。

// 简单介绍:
$project: {
    [字段名]: 1 or true || 0 or false
}

/**
* value 为 1 or true,表示取出该字段 
* value 为 0 or false,则表示排除该字段 
*/


// 例如:
$project: {
    _id: 1,
    imgUrl: 1
}
结果就是只取出 { _id: "", imgUrl: "" }

$project: {
    createTime: 0
}
结果就是除了createTime,其他的字段都查出来

应用到实际例子中

await artworkRepo.aggregate([
   { $match: { _id: { $eq: new ObjectID(artworkId) } } },
   {
       $project: {
           _id: 1,
           imgUrl: 1
       }
   }
]).toArray()

$group

$group 会按指定的 _id 表达式对输入文档进行分组,其实看它的名字就知道是分组用的。我看下面的这个例子,查了三个表,输出的字段是非常多的,我不用这么多字段啊,而且我只想要下面这种结构,不想要嵌套有数组。(我这个例子可能不太合适,读者请自行辨别)

{
    userId: "",
    artworkId: "",
    commentId: ""
}

// 不想要其他字段
import { ObjectID } from "mongodb";

async function getUserArtwork(userId: string) {
    // 1.user表
   const res = await userRepo.aggregate([
       { 
          $match: { _id: { $eq: new ObjectID(userId) } } 
       },
       {
          $addFields: { _userId: "$_id" },
       },
       // 2.作品表
       {
         $lookup: {
           from: "artworks",
           let: { userId: "$_id" }, // 定义一个变量 ( users表中的_id )
           pipeline: [
           {
              $addFields: {
                _artworkId: "$_id", // 作品表中的作品ID
              },
            },
            {
              $match: {
                $expr: {
                  $eq: ["$authorId", "$$userId"], // authorId == userId
                },
                isShow: true
              },
            },
            // 3.评论表
            {
              $lookup: {
                from: "artwork_comment",
                localField: "_artworkId", // 作品表中的作品ID
                foreignField: "artworkId",
                as: "comments",
              },
            },
          ],
          as: "artworks", // 起一个别名
         },
       },
       {
            $unwind: {
              path: "$artworks", // 这个变量 就是上面的 as: "artworks"
              // 如果不设置为true允许为空,那么如果为空,就不会输出这一条记录
              preserveNullAndEmptyArrays: true, 
            },
        },
        {
            // 这里访问的 $artworks,是 $unwind 定义的
            $group: {
              // 这个_id 是 必须的,因为需要用到这个_id来分组
              _id: "$_userId", // 这个是 $addFields 一开始我定义的 _userId
              userId: "$_userId",
              artworkId: { $last: { "$artworks._id" } }
              commentId: { $last: { $last: { "$artworks.comments._id" } } }
            },
          },
    ]).toArray();
}

$unwind

$unwind 操作符的用法最好是看管方文档,这里我就不展开了。

好了,上面就得到了我想要的数据结构啦,主要是 $unwind$group 操作符的运用。

写在最后

至此,文章就分享完毕了,欢迎在评论区交流。
如果文章对你有所帮助,不要忘了点上宝贵的一赞!
听说点赞的人运气都不差,相信来年第一个升职加薪的一定是你~