MongoDB 中的 $unwind 操作符是什么?

这是我加入 MongoDB 的第一天,所以请对我好一点:)

我不能理解 $unwind操作员,也许是因为英语不是我的母语。

db.article.aggregate(
{ $project : {
author : 1 ,
title : 1 ,
tags : 1
}},
{ $unwind : "$tags" }
);

项目操作符是我可以理解的,我想(它就像 SELECT,不是吗?)但是,$unwind(引用) 为每个源文档中的每个取消数组成员返回一个文档

这是 JOIN吗?如果是,$project的结果(包括 _idauthortitletags字段)如何与 tags阵列进行比较?

注意 : 我从 MongoDB 网站上找到了这个例子,我不知道 tags数组的结构。我认为这是一个简单的标签名数组。

114078 次浏览

$unwind复制管道中的每个文档,每个数组元素复制一次。

因此,如果您的输入管道包含一个文章 doc,其中有 tags中的两个元素,那么 {$unwind: '$tags'}将把管道转换为除 tags字段之外相同的两个文章 doc。在第一个文档中,tags将包含来自原始文档数组的第一个元素,而在第二个文档中,tags将包含第二个元素。

首先,欢迎来到 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个项组成的数组,在这个例子中是“ fun”、“ good”和“ fun”。

$unwind 所做的就是为每个元素剥离一个文档并返回结果文档。 在传统的方法中考虑这个问题,它相当于“对于标记数组中的每个项,只返回一个包含该项的文档”。

因此,运行以下命令的结果是:

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
}

请注意,结果数组中唯一发生变化的是在标记值中返回的内容。如果你需要一个额外的参考如何工作,我已经包括了一个链接 给你。希望这会有所帮助,并且祝您在进入我迄今为止遇到的最好的 NoSQL 系统之一时一切顺利。

让我用一种与关系数据库管理系统相关的方式来解释:

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 作者,标题,标签 来自文章

接下来是 Mongo 的有趣部分,考虑这个数组 tags : [ "fun" , "good" , "fun" ]作为另一个相关的表(不能是一个查找/引用表,因为值有一些重复)命名为“标记”。请记住,SELECT 通常生成垂直的东西,所以展开“标记”是将 Split ()垂直地放入表“标记”中。

$project + $unwind 的最终结果: enter image description here

将输出转换为 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”字段,所以它是自动添加的。

关键是要使它像表一样执行聚合。

根据蒙戈德布的官方文件:

解构输入文档中的数组字段,为每个元素输出一个文档。每个输出文档都是输入文档,数组字段的值由元素替换。

通过基本例子解释:

托收清单包括以下文件:

{ "_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 }

下面的 $放松操作是等价的,并为 尺寸字段中的每个元素返回一个文档。如果 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/

考虑下面的例子来理解这一点 集合中的数据

{
"_id" : 1,
"shirt" : "Half Sleeve",
"sizes" : [
"medium",
"XL",
"free"
]
}

Query —— db.test1.total ([{ $unwind: “ $size”}]) ;

输出

{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "medium" }
{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "XL" }
{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "free" }