一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
本文内容:
1.一条简单的聚合查询语句。
2.连表查询,用第一个表的条件,去查第二个表的数据。
3.一段查询语句查询三个表,递进查询。
前言
本文主要是介绍mongodb聚合查询语句的灵活用法,文章用到的是 mongodb + orm 的方式来操作数据库。
一条简单的聚合查询语句
假设有个作品表 artworkRepo,前端传了一个作品ID artworkId 进来查某个作品信息,我们可以这样做
import { ObjectID } from "mongodb";
async function getArtworkByArtworkId(artworkId: string) {
const res = await artworkRepo.aggregate([
{ $match: { _id: { $eq: new ObjectID(artworkId) } } },
]).toArray();
}
其中 $match 操作符,是条件操作符,就是放查询条件的地方,相当于一个过滤器。$eq 操作符对比两个数是否相等。这里也可以写成 _id: new ObjectID(artworkId)。我这里的_id在数据库中的类型是objectId,而前端传过来的是 string 类型,所以需要转一下类型,在使用过程中要按实际情况来使用。
连表查询
接下来我们就开始连表查询的语句。
假设作品表中有一个作者ID authorId ,我现在要在查询作品的同时把作者的信息查询出来,我应该怎么做呢?一个方法是,先用一条查询语句查出作品的信息,从返回的结果中取出 authorId,再写一条语句,根据 authorId 去查作者信息。第二个方法就是,用连表查询来查,两种方法都可以,看你怎么用,我们来看第二种方法怎么实现。
import { ObjectID } from "mongodb";
async function getArtworkByArtworkId(artworkId: string) {
const res = await artworkRepo.aggregate([
{
$match: { _id: { $eq: new ObjectID(artworkId) } }
},
// $addFields操作符 相当与定义了一个变量,$authorId 是 作品表里的 authorId
{ $addFields: { _authorId: "$authorId" } },
{
$lookup: {
from: "users", // 用户表
localField: "_authorId", // $addFields 中定义的变量
foreignField: "_id", // 这个是 users 表中的 _id
as: "author", // 起一个别名
},
},
]).toArray();
}
返回的数据大概是这样的:
res = [
{
_id: testtest...,
authorId: testtest...,
author: [...]
}
]
那如果我查第二个表的时候,也需要根据几个条件来查呢,这时又该怎么做呢?
$lookup 有没有其他的写法呢?答案是有的,接下来就来实现一下。
刚才是根据作品表查作者,那现在反过来。
import { ObjectID } from "mongodb";
async function getUserArtwork(userId: string) {
const res = await userRepo.aggregate([
{
$match: { _id: { $eq: new ObjectID(userId) } }
},
{
$lookup: {
from: "artworks", // 作品表
let: { userId: "$_id" }, // 定义一个变量 ( users表中的_id )
pipeline: [
{
$match: {
$expr: {
$eq: ["$authorId", "$$userId"], // authorId == userId
},
isShow: true
},
},
],
as: "artworks", // 起一个别名
},
},
]).toArray();
}
现在第二个表也有条件限制啦,这里主要理解 pipeline 的用法。
一段查询语句查询三个表,递进查询
作品中有其对应中评论内容,作品的评论在评论表中,怎么查呢,一个方法就是分开查询啦,第二个方法就是在同一段语句中写查询语句,接下来就着手实现吧!
观察上面 pipeline 中的代码,可以发现,其中的结构,和上一层的结构几乎一样,所以mongodb让我们可以在 pipeline 继续使用 $lookup
import { ObjectID } from "mongodb";
async function getUserArtwork(userId: string) {
const res = await userRepo.aggregate([
{
$match: { _id: { $eq: new ObjectID(userId) } }
},
{
$lookup: {
from: "artworks", // 作品表
let: { userId: "$_id" }, // 定义一个变量 ( users表中的_id )
pipeline: [
{
$addFields: {
_artworkId: "$_id", // 作品表中的作品ID
},
},
{
$match: {
$expr: {
$eq: ["$authorId", "$$userId"], // authorId == userId
},
isShow: true
},
},
// 这里是第三个表啦
{
$lookup: {
from: "artwork_comment",
localField: "_artworkId", // 作品表中的作品ID
foreignField: "artworkId",
as: "comments",
},
},
],
as: "artworks", // 起一个别名
},
},
]).toArray();
}
写在最后
至此,文章就分享完毕了,欢迎在评论区交流。
如果文章对你有所帮助,不要忘了点上宝贵的一赞!
听说点赞的人运气都不差,相信来年第一个升职加薪的一定是你~