MongoDB 中的 $unwind 运算符是啥?
Posted
技术标签:
【中文标题】MongoDB 中的 $unwind 运算符是啥?【英文标题】:What's the $unwind operator in MongoDB?MongoDB 中的 $unwind 运算符是什么? 【发布时间】:2013-05-03 03:01:40 【问题描述】:这是我使用 MongoDB 的第一天,所以请放轻松:)
我听不懂$unwind
运算符,可能是因为英语不是我的母语。
db.article.aggregate(
$project :
author : 1 ,
title : 1 ,
tags : 1
,
$unwind : "$tags"
);
项目运营商是我可以理解的,我想(就像SELECT
,不是吗?)。但是随后,$unwind
(引用)为每个源文档中展开数组的每个成员返回一个文档。
这像JOIN
吗?如果是,如何将$project
(带有_id
、author
、title
和tags
字段)的结果与tags
数组进行比较?
注意:我是从MongoDB网站上拿的例子,我不知道tags
数组的结构。我认为这是一个简单的标签名称数组。
【问题讨论】:
【参考方案1】:$unwind
复制管道中的每个文档,每个数组元素一次。
因此,如果您的输入管道包含一个文章文档,其中 tags
中有两个元素,$unwind: '$tags'
会将管道转换为两个相同的文章文档,除了 tags
字段。在第一个文档中,tags
将包含原始文档数组中的第一个元素,在第二个文档中,tags
将包含第二个元素。
【讨论】:
【参考方案2】:首先,欢迎来到 MongoDB!
要记住的是,MongoDB 采用“NoSQL”方法来存储数据,因此请从您的脑海中消除选择、连接等的想法。它以文档和集合的形式存储您的数据,这允许以动态方式从您的存储位置添加和获取数据。
话虽如此,为了理解 $unwind 参数背后的概念,您首先必须了解您试图引用的用例在说什么。来自mongodb.org的示例文档如下:
title : "this is my title" ,
author : "bob" ,
posted : new Date () ,
pageViews : 5 ,
tags : [ "fun" , "good" , "fun" ] ,
comments : [
author :"joe" , text : "this is cool" ,
author :"sam" , text : "this is bad"
],
other : foo : 5
注意标签实际上是一个包含 3 个项目的数组,在本例中是“有趣”、“好”和“有趣”。
$unwind 的作用是允许您为每个元素剥离一个文档并返回该结果文档。 用经典的方法来考虑这一点,相当于“对于 tags 数组中的每个项目,返回一个仅包含该项目的文档”。
因此,运行结果如下:
db.article.aggregate(
$project :
author : 1 ,
title : 1 ,
tags : 1
,
$unwind : "$tags"
);
将返回以下文件:
"result" : [
"_id" : ObjectId("4e6e4ef557b77501a49233f6"),
"title" : "this is my title",
"author" : "bob",
"tags" : "fun"
,
"_id" : ObjectId("4e6e4ef557b77501a49233f6"),
"title" : "this is my title",
"author" : "bob",
"tags" : "good"
,
"_id" : ObjectId("4e6e4ef557b77501a49233f6"),
"title" : "this is my title",
"author" : "bob",
"tags" : "fun"
],
"OK" : 1
请注意,结果数组中唯一改变的是标签值中返回的内容。如果您需要有关其工作原理的其他参考,我提供了一个链接 here。希望这对您有所帮助,并祝您在尝试我迄今为止遇到的最好的 NoSQL 系统之一时好运。
【讨论】:
如果标签是嵌入式文档,我将如何做到这一点。比如$summary.tags
....然后我想删除重复并计算$size。
非常感谢您的解释【参考方案3】:
让我以一种与 RDBMS 相关的方式进行解释。这是声明:
db.article.aggregate(
$project :
author : 1 ,
title : 1 ,
tags : 1
,
$unwind : "$tags"
);
申请文件/记录:
title : "this is my title" ,
author : "bob" ,
posted : new Date () ,
pageViews : 5 ,
tags : [ "fun" , "good" , "fun" ] ,
comments : [
author :"joe" , text : "this is cool" ,
author :"sam" , text : "this is bad"
],
other : foo : 5
$project / Select 只是将这些字段/列返回为
SELECT作者、标题、标签FROM文章
接下来是 Mongo 的有趣部分,将这个数组 tags : [ "fun" , "good" , "fun" ]
视为另一个名为“tags”的相关表(不能是查找/引用表,因为值有一些重复)。请记住 SELECT 通常会产生垂直的东西,因此展开“标签”是将 split() 垂直地拆分为表格“标签”。
$project + $unwind 的最终结果:
将输出转换为 JSON:
"author": "bob", "title": "this is my title", "tags": "fun",
"author": "bob", "title": "this is my title", "tags": "good",
"author": "bob", "title": "this is my title", "tags": "fun"
因为我们没有告诉 Mongo 省略“_id”字段,所以它是自动添加的。
关键是让它像表格一样进行聚合。
【讨论】:
或另一种思考方式是 UNION ALL【参考方案4】:根据 mongodb 官方文档:
$unwind 从输入文档中解构一个数组字段,为每个元素输出一个文档。每个输出文档都是输入文档,其中数组字段的值被元素替换。
通过基本示例进行说明:
收集清单具有以下文件:
"_id" : 1, "item" : "ABC", "sizes": [ "S", "M", "L"]
"_id" : 2, "item" : "EFG", "sizes" : [ ]
"_id" : 3, "item" : "IJK", "sizes": "M"
"_id" : 4, "item" : "LMN"
"_id" : 5, "item" : "XYZ", "sizes" : null
以下 $unwind 操作是等效的,并为 sizes 字段中的每个元素返回一个文档。如果 size 字段未解析为数组但未丢失、null 或空数组,则 $unwind 会将非数组操作数视为单个元素数组。
db.inventory.aggregate( [ $unwind: "$sizes" ] )
或
db.inventory.aggregate( [ $unwind: path: "$sizes" ]
以上查询输出:
"_id" : 1, "item" : "ABC", "sizes" : "S"
"_id" : 1, "item" : "ABC", "sizes" : "M"
"_id" : 1, "item" : "ABC", "sizes" : "L"
"_id" : 3, "item" : "IJK", "sizes" : "M"
为什么需要它?
$unwind 在执行聚合时非常有用。它在执行排序、搜索等各种操作之前将复杂/嵌套文档分解为简单文档。
要了解有关 $unwind 的更多信息:
https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/
要了解有关聚合的更多信息:
https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
【讨论】:
【参考方案5】:考虑下面的例子来理解这一点 集合中的数据
"_id" : 1,
"shirt" : "Half Sleeve",
"sizes" : [
"medium",
"XL",
"free"
]
查询 -- db.test1.aggregate( [ $unwind : "$sizes" ] );
输出
"_id" : 1, "shirt" : "Half Sleeve", "sizes" : "medium"
"_id" : 1, "shirt" : "Half Sleeve", "sizes" : "XL"
"_id" : 1, "shirt" : "Half Sleeve", "sizes" : "free"
【讨论】:
以上是关于MongoDB 中的 $unwind 运算符是啥?的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB Aggregation - $unwind order 文档是不是与嵌套数组 order 相同
使用 $unwind、$lookup 和 $group 的复杂聚合中的 mongodb 正确列表顺序