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

xxhby3vn  于 2022-12-26  发布在  Go
关注(0)|答案(5)|浏览(169)

这是我在MongoDB的第一天,所以请对我放松:)
我不懂$unwind运算符,可能是因为英语不是我的母语。

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

我想项目操作符是我能理解的(它就像SELECT,不是吗?),但是$unwind(引用)* 为每个源文档 * 中的展开数组的每个成员返回一个文档。
这是否类似于JOIN?如果是,$project(包含_idauthortitletags字段)的结果如何与tags数组进行比较?

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

myzjeezk

myzjeezk1#

需要记住的是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 }
}

请注意,tags实际上是一个包含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
}

注意,结果数组中唯一改变的是tags值中返回的内容,如果你需要更多的参考来了解它是如何工作的,我已经包含了一个链接here

0s0u357o

0s0u357o2#

$unwind复制管道中的每个文档,每个数组元素复制一次。
因此,如果您的输入管道包含一个文章文档,其中tags中有两个元素,则{$unwind: '$tags'}会将管道转换为两个相同的文章文档(除了tags字段外)。在第一个文档中,tags将包含原始文档数组中的第一个元素,而在第二个文档中,tags将包含第二个元素。

kuuvgm7e

kuuvgm7e3#

考虑下面的示例来理解集合中的此数据

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

查询-- db.test1.aggregate([ { $展开:“$大小”} ]);
输出

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

w3nuxt5m4#

根据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字段中的每个元素返回一个文档。如果sizes字段未解析为数组,但不缺失、不为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/

cgfeq70w

cgfeq70w5#

让我用一种与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**只是将这些字段/列返回为

选择作者、标题、标签来源文章

接下来是Mongo有趣的部分,把这个数组tags : [ "fun" , "good" , "fun" ]当作另一个名为“tags”的相关表(不能是查找/引用表,因为值有一些重复)。记住SELECT通常产生垂直的东西,所以展开“tags”就是**split()**垂直地将表“tags”。
$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”字段,所以它是自动添加的。
关键是要使它像表一样执行聚合。

相关问题