服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - MongoDB - MongoDB中如何使用JOIN操作详解

MongoDB中如何使用JOIN操作详解

2020-05-13 19:23都市烟火 MongoDB

相信大家都知道mongodb是不支持join操作的,因此我们只能自己来实现这个功能。所以下面这篇文章主要给大家介绍了关于在MongoDB中如何使用JOIN操作的相关资料,文中通过示例代码介绍的非常详细,需要的朋友们下面来一起看看吧。

前言

MongoDB是由C++语言所编写的一种面向文档的非关系型数据库(是一种NoSql数据库实现),也是介于关系型数据库和非关系型数据库之间的数据存储产品,而众所周知SQL与NoSQL最大的不同之一就是不支持JOIN,在传统的数据库中,SQL JOIN子句允许你使用普通的字段,在两个或者是更多表中的组合表中的每行数据。例如,如果你有表books和publishers,你可以像下面这样写命令:

?
1
2
3
SELECT book.title, publisher.name
FROM book
LEFT JOIN book.publisher_id ON publisher.id;

换句话说,book表中的publisher_id字段引用了publishers表中的id字典。这些都是很常见的例子:对于每个publisher都可以拥有成千上万本书,如果你想更新publisher的信息的时候,我们只需要更改一条记录。数据的冗余是很小的,因为我们不需要为每本书来重复更新他的publisher信息,这种技术已基本当做一种规范化的东西了。SQL数据库提供了一些列的规范与约束条件来保障数据关联性。

--------------------------------------------------------------------------------

NoSQL == No JOIN?

并不都是这样吧。。。。。

--------------------------------------------------------------------------------

面向文档的数据库,例如MongoDB,被设计用来存储非结构化的数据,理想情况下,这些数据是在数据集合中是相互没有关联的,如果一条数据包含两次或者更多次,那数据就重复了。因为大部分情况下我们还是需要数据关联的,只有很少的情况下才会不需要关联数据,看来NoSQL这些特性看来让人失望啊。幸运的是MongoDB 3.2 介绍了一个新的$lookup操作,这个操作可以提供一个类似于LEFT OUTER JOIN的操作在两个或者是更多的条件下。

--------------------------------------------------------------------------------

MongoDB Aggregation

$lookup仅仅在 aggregation操作中才被允许使用,想想他作为一个管道操作:查询,过滤,组合结果。一个操作的输出被作为下一个的输入。Aggregation比简单的查询操作更难于理解,而且这些操作通常运行很慢,然而他们很高效,Aggregation可以使用一个很好的例子来解释,假设我们使用user数据集合来创建一个社交平台,在每个独立的文档中存储没个用户的信息,例如:

?
1
2
3
4
5
6
7
{
 "_id": ObjectID("45b83bda421238c76f5c1969"),
 "name": "User One",
 "email: "userone@email.com",
 "country": "UK",
 "dob": ISODate("1999-09-13T00:00:00.000Z")
}

我们可以向user这个集合中添加足够多的用户,但是每个MongoDB文档都必须有一个为一个_id字段值,这个_id字段值就像SQL中的键,在我们没有明确指定_id的时候会被自动的加入到文档中。我们的社交网站现在需要一个post集合,这个结合存储用户的评论,这个文档存储纯文本,时间,评分,一个被写到user_id字段的玩家引用。

?
1
2
3
4
5
6
7
{
 "_id": ObjectID("17c9812acff9ac0bba018cc1"),
 "user_id": ObjectID("45b83bda421238c76f5c1969"),
 "date: ISODate("2016-09-05T03:05:00.123Z"),
 "text": "My life story so far",
 "rating": "important"
}

我们现在想要显示最近具有important评论的二十条数据,这些数据来自所有的用户,并且是按照时间排序的。每一个返回的文档中应该包含评论的文本,发布评论的时间,以及相关的用户的名字和国家。

MongoDB数据库的aggregate查询是通过传递管道操作的数组,这个数组中顺序的定了每个操作。首先,我们需要从所有的post集合中提取出所有的文档,这些文档使用$match记性准确rating过滤。

?
1
{ "$match": { "rating": "important" } }

我们现在需要对过滤出来的文档按照时间,使用$sort操作进行排序。

?
1
{ "$sort": { "date": -1 } }

因为我们要仅仅返回二十条数据,我们可以使用$limit来限制我们需要处理的文档数量。

?
1
{ "$limit": 20 }

我们现在使用$lookup操作从user集合中连接数据,这个操作需要一个四个参数的对象:

      1、localField:在输入文档中的查找字段

      2、from:需要连接的集合

      3、foreignField:需要在from集合中查找的字段

      4、as:输出的字段名字

所以我们的操作是这样的:

?
1
2
3
4
5
6
{ "$lookup": {
 "localField": "user_id",
 "from": "user",
 "foreignField": "_id",
 "as": "userinfo"
} }

在我们的输出中将会创建一个名为userinfo的新字段,他是一个数组,其中每个元素都是在user集合中匹配的元素。

?
1
2
3
"userinfo": [
 { "name": "User One", ... }
]

在post.user_id与user._id之间,我们具有一对一的关系,因为对于每一个post只有一个用户。因此我们的userinfo数组将会仅仅包含一个元素,我们可以说使用 $unwind操作来解构他并插入到一个自文档中。

?
1
{ "$unwind": "$userinfo" }

现在的输出将会转化成更加常用的结构:

?
1
2
3
4
5
"userinfo": {
 "name": "User One",
 "email: "userone@email.com",
 
}

最终我们可以在管道中使用 $project操作返回评论信息,评论的时间,评论的用户名,国家等。

?
1
2
3
4
5
6
{ "$project": {
 "text": 1,
 "date": 1,
 "userinfo.name": 1,
 "userinfo.country": 1
} }

合并上面所有的操作

我们最终的聚合查询匹配的评论,按照顺序排序,限制最新的二十条信息,连接用户的数据,扁平用户数组,最后只返回我们需要的必须数据,总的命令如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
db.post.aggregate([
 { "$match": { "rating": "important" } },
 { "$sort": { "date": -1 } },
 { "$limit": 20 },
 { "$lookup": {
 "localField": "user_id",
 "from": "user",
 "foreignField": "_id",
 "as": "userinfo"
 } },
 { "$unwind": "$userinfo" },
 { "$project": {
 "text": 1,
 "date": 1,
 "userinfo.name": 1,
 "userinfo.country": 1
 } }
]);

结果是一个拥有二十个文档的集合,例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[
 {
 "text": "The latest post",
 "date: ISODate("2016-09-27T00:00:00.000Z"),
 "userinfo": {
  "name": "User One",
  "country": "UK"
 }
 },
 {
 "text": "Another post",
 "date: ISODate("2016-09-26T00:00:00.000Z"),
 "userinfo": {
  "name": "User One",
  "country": "UK"
 }
 }
 ...
]

MongoDB的$lookup很好用而且很高效,但是上面这个基础的例子只是一个组合的集合查询。他不是一个对SQL中的更加高效的JOIN子句的替代。而且MongoDB也提供了一些限制,如果user集合被删除了,post文档还是会保留。

理想情况下,这个$lookup操作应该不会经常使用,如果你需要经常使用它,那么你就使用了错误的数据存储了(数据库):如果你有相关联的数据,应该使用关联数据库(SQL)。

也就是说$lookup是一个MongoDB 3.2新加入的,他解决了当在Nosql数据库中使用一些小的相关联的数据查询的时候一些令人失望的问题。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:http://www.cnblogs.com/duhuo/p/6068879.html

延伸 · 阅读

精彩推荐
  • MongoDB迁移sqlserver数据到MongoDb的方法

    迁移sqlserver数据到MongoDb的方法

    这篇文章主要介绍了迁移sqlserver数据到MongoDb的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    听枫xl9682021-01-03
  • MongoDBMongoDB 内存使用情况分析

    MongoDB 内存使用情况分析

    都说 MongoDB 是个内存大户,但是怎么知道它到底用了多少内存呢...

    MongoDB教程网10002020-09-29
  • MongoDBMongoDB安装图文教程

    MongoDB安装图文教程

    这篇文章主要为大家详细介绍了MongoDB安装图文教程,分为两大部分为大家介绍下载MongoDB和安装MongoDB的方法,感兴趣的小伙伴们可以参考一下 ...

    Yangyi.He6132020-05-07
  • MongoDBmongodb基本命令实例小结

    mongodb基本命令实例小结

    这篇文章主要介绍了mongodb基本命令,结合实例形式总结分析了MongoDB数据库切换、查看、删除、查询等基本命令用法与操作注意事项,需要的朋友可以参考下...

    dawn-liu3652020-05-26
  • MongoDBMongoDB中javascript脚本编程简介和入门实例

    MongoDB中javascript脚本编程简介和入门实例

    作为一个数据库,MongoDB有一个很大的优势——它使用js管理数据库,所以也能够使用js脚本进行复杂的管理——这种方法非常灵活 ...

    MongoDB教程网6982020-04-24
  • MongoDB分布式文档存储数据库之MongoDB分片集群的问题

    分布式文档存储数据库之MongoDB分片集群的问题

    这篇文章主要介绍了分布式文档存储数据库之MongoDB分片集群的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...

    Linux-18743072020-12-20
  • MongoDBMongoDB凭什么跻身数据库排行前五

    MongoDB凭什么跻身数据库排行前五

    MongoDB以比去年同期超出65.96分的成绩继续雄踞榜单前五,这个增幅在全榜仅次于PostgreSQL的77.99,而其相对于4月份的6.10分的增长也是仅次于微软SQL Server排名...

    孙浩峰3892020-05-22
  • MongoDBMongodb实现定时备份与恢复的方法教程

    Mongodb实现定时备份与恢复的方法教程

    这篇文章主要给大家介绍了Mongodb实现定时备份与恢复的方法教程,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面...

    chenjsh364522020-05-13