对比关系型数据库 , MongoDB 关联表查询 ,

文章目录[隐藏]

mongodb 是一个文档型的数据库,而且它也是最像关系型数据库的一种 nosql,在这之前,我们可以使用DbRef,但是,在mongodb 3.2 中增加了一个相当牛逼的手段,那就是$lookup,而且放到了aggreation这种重量级的pipeline分析框架上了

准备

首先准备一些数据, 俩张 collection 表进行关联

// 班级建表
db.clases.insert([
    {
        "_id": 1,
        "className": "五年一班",
        "doc": "五年一班的描述"
    },
    {
        "_id": 2,
        "className": "五年二班",
        "doc": "五年二班的描述"
    }
])

// 学生建表
db.students.insert([
    {
        "_id": 1,
        "studentName": "马一",
        "className": "五年一班",
        "doc": "马一的描述"
    },
    {
        "_id": 2,
        "studentName": "马二",
        "className": "五年一班",
        "doc": "马二的描述"
    },
    {
        "_id": 3,
        "studentName": "马三",
        "className": "五年二班",
        "doc": "马三的描述"
    }
])

学生 与 班级 自然就存在着一个外键关系 , 这里为了直观 , student 没有引用clases的 _id 而是引的 className

Aggregate

Aggregation Pipeline

聚合管道运算符 官方文档
Aggregation Pipeline Operators

MongoDB聚合管道

使用聚合管道可以对集合中的文档进行变换和组合。 管道是由一个个功能节点组成的,这些节点用管道操作符来进行表示。聚合管道以一个集合中的所有文档作为开始,然后这些文档从一个操作节点流向下一个节点 ,每个操作节点对文档做相应的操作。这些操作可能会创建新的文档或者过滤掉一些不符合条件的文档,在管道中可以对文档进行重复操作。 管道表达式只可以操作当前管道中的文档,不能访问其他的文档:表达式操作可以在内存中完成对文档的转换。

$lookup [多表关联(3.2版本新增)]

用于与统一数据库中其他集合之间进行 join 操作

  1. from 同一个数据库下等待被 Join 的集合。
  2. localField 源集合中的 match 值 [主键ID(className)]
  3. foreignField 待Join的集合的match值,[外键ID(className)]
  4. as 为输出文档的新增值命名,将foreign的表输出到此命名下
// 关联查询
db.clases.aggregate([
    {
        "$lookup": 
        {
            "from": "students",
            "localField": "className",
            "foreignField": "className",
            "as": "docs"
        }
    }
])

查询结果如下

$project

指定输出文档里的字段. 类似于 sql 中 select * 中的 ‘*’
这里直接过滤掉 clases表字段, 只显示 student

db.clases.aggregate([
    {
        "$lookup": 
        {
            "from": "students",
            "localField": "className",
            "foreignField": "className",
            "as": "docs"
        },
    },
    {
        // 只显示 docs
        "$project": {
            "_id": 0,
            "docs": 1
        }
    }
])

$unwind

unwind 可以将 lookup 中 as 输出的集合转化为 collection 文档 ,
这一步还是很有必要的 , 之后关联查询 根据 foreign 表条件过滤查询的时候 需要这一步

db.clases.aggregate([
    {
        "$lookup": 
        {
            "from": "students",
            "localField": "className",
            "foreignField": "className",
            "as": "docs"
        },
    },
    {
        // 只显示 docs
        "$project": {
            "_id": 0,
            "docs": 1
        }
    },
    {
        "$unwind": "$docs"
    }
])

$match

match 类似于 sql 的where ? having ?
注意 $project 要放后面, 顺序不能错

// 关联查询
db.clases.aggregate([
    {
        "$lookup": 
        {
            "from": "students",
            "localField": "className",
            "foreignField": "className",
            "as": "docs"
        },
    },
    {
        // 用$unwind将其分割嵌入,作为u字段的子文档
        "$unwind": "$docs"
    },
    {
        // 添加筛选条件
        "$match": {
            // 左表筛选
            "className": "五年级一班",
            // 右表筛选
            "docs.studentName": "马一"
        }
    },
    {
        // 只显示 docs
        "$project": {
            "_id": 0,
            "docs": 1
        }
    }
])

加上条件后,只有一条记录了

voidm

在黑暗中支撑和平的无名者

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐