如何使用$ unwind将文档保存在聚合中

时间:2013-11-14 10:59:35

标签: mongodb aggregation-framework

假设我有三个学生......

爱丽丝,她星期五一直在那里。

{
    "name" : "Alice",
    "goes" : {
        "mondays" : {
            "fr" : 900,
            "to" : 1400
        },
        "fridays" : {
            "fr" : 700,
            "to" : 1600
        },
    }
}

鲍勃,这里应该在1月1日那里

{
    "_id" : ObjectId("5284a7085d60338b40b8f17d"),
    "name" : "Bob",
    "goes" : {
        "mondays" : {
            "fr" : 800,
            "to" : 1200
        },
        "special" : [ 
            {
                "date" : "2010-01-01",
                "fr" : 1000,
                "to" : 1500
            }
        ]
    }
}

而且克莱尔将不会在星期一或10.00

参加
{
    "_id" : ObjectId("5284c2785d60338b40b8f17f"),
    "name" : "Clair",
    "goes" : {
        "wednesdays" : {
            "fr" : 1100,
            "to" : 1500
        },
        "special" : [ 
            {
                "date" : "2010-01-01",
                "fr" : 1600,
                "to" : 1900
            }, 
            {
                "date" : "2010-01-02",
                "fr" : 1000,
                "to" : 1300
            }
        ]
    }
}

我想找到所有应该在2010年1月1日星期五7点10分参加的学生

所以我用聚合框架来做这件事。

db.students.aggregate(
    [
        {
            $unwind: "$goes.special"
        },
        {
            $match: {
                $or : [
                    {
                        'goes.fridays.fr': 700,
                    },
                    {
                        'goes.special.date' : '2010-01-01',
                        'goes.special.fr': 1000
                    }
                ]
            }
        }
    ]
)

但爱丽丝没有露面。它清楚地说明了为什么在mongodb文档中,http://docs.mongodb.org/manual/reference/operator/aggregation/unwind/位于最底层。

  

“如果为$ unwind指定一个包含空数组的目标字段   ([])在输入文档中,管道忽略输入文档,   并且不会生成结果文件。“

我可以通过添加一个带有空值的数组来解决它,但这并不是一个很好的解决方案。

有没有办法放松我不要忽略$ unwind'ed数组中没有数据的文件?

1 个答案:

答案 0 :(得分:1)

您根本不需要$unwind。管道中的简单$match就足够了:

pipeline = [
    {
        "$match" : {
            "$or" : [
                {
                    "goes.fridays.fr" : 700
                },
                {
                    "goes.special" : {
                        "$elemMatch" : {
                            "date" : "2010-01-01",
                            "fr" : 1000
                        }
                    }
                }
            ]
        }
    }
]

db.students.aggregate(pipeline)

即使没有聚合框架,也可以轻松完成。

query = {
    "$or" : [
        {
            "goes.fridays.fr" : 700
        },
        {
            "goes.special" : {
                "$elemMatch" : {
                    "date" : "2010-01-01",
                    "fr" : 1000
                }
            }
        }
    ]
}

db.students.find(query)