130

这是我使用 MongoDB 的第一天,所以请放轻松 :)

我听不懂$unwind接线员,可能是因为英语不是我的母语。

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

我想,项目操作员是我能理解的(就像SELECT,不是吗?)。但是,$unwind(引用)为每个源文档中展开数组的每个成员返回一个文档

这像JOIN吗?如果是,如何将$project(with _id, author, titleand tagsfields) 的结果与tags数组进行比较?

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

4

5 回答 5

310

首先,欢迎来到 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 的作用是允许您为每个元素剥离一个文档并返回该结果文档。以经典方法来考虑这一点,相当于“对于标签数组中的每个项目,返回一个仅包含该项目的文档”。

因此,运行以下结果:

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 系统之一时好运。

于 2013-05-08T19:32:22.577 回答
53

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

因此,如果您的输入管道包含一篇文章文档,其中包含两个元素tags{$unwind: '$tags'}则将管道转换为两个文章文档,除了tags字段之外,它们都是相同的。在第一个文档中,tags将包含原始文档数组中的第一个元素,在第二个文档中,tags将包含第二个元素。

于 2013-05-08T19:17:18.060 回答
10

consider the below example to understand this Data in a collection

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

Query -- db.test1.aggregate( [ { $unwind : "$sizes" } ] );

output

{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "medium" }
{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "XL" }
{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "free" }
于 2019-08-01T18:22:56.997 回答
5

根据 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/

于 2018-10-25T05:27:34.050 回答
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只是将这些字段/列返回为

文章中选择作者、标题、标签

接下来是 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" 字段,所以它是自动添加的。

关键是让它像表格一样执行聚合。

于 2017-04-09T23:37:13.680 回答