MongoDB中使用JOIN操作的方法

65次阅读
没有评论

共计 3698 个字符,预计需要花费 10 分钟才能阅读完成。

自动写代码机器人,免费开通

这篇文章给大家分享的是有关 MongoDB 中使用 JOIN 操作的方法的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,一起跟随丸趣 TV 小编过来看看吧。

前言

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

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 数据集合来创建一个社交平台,在每个独立的文档中存储没个用户的信息,例如:

{  _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 字段的玩家引用。

{  _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 过滤。

{  $match : {  rating :  important  } }

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

{  $sort : {  date : -1 } }

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

{  $limit : 20 }

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

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

  2、from:需要连接的集合

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

  4、as:输出的字段名字

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

{  $lookup : {
  localField :  user_id ,
  from :  user ,
  foreignField :  _id ,
  as :  userinfo 
} }

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

userinfo : [ {  name :  User One , ... }
]

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

{  $unwind :  $userinfo  }

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

userinfo : {
  name :  User One ,
  email:  userone@email.com ,
 …
}

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

{  $project : {
  text : 1,
  date : 1,
  userinfo.name : 1,
  userinfo.country : 1
} }

合并上面所有的操作

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

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
 } }
]);

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

[
 {
  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 数据库中使用一些小的相关联的数据查询的时候一些令人失望的问题。

感谢各位的阅读!关于“MongoDB 中使用 JOIN 操作的方法”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向 AI 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计3698字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)