MongoDB多个数组展开

22

我有以下文档:

{
  "dates": [
    1399518702000,
    1399126333000,
    1399209192000,
    1399027545000
  ],
  "dress_number": "4",
  "name": "J. Evans",
  "numbers": [
    "5982",
    "5983",
    "5984",
    "5985"
  ]
}

能否从多个数组解开数据并仅获取数组中成对的元素:

{
    "dates": "1399518702000",
    "numbers": "5982"
},
{
    "dates": "1399126333000",
    "numbers": "5983"
},
{
    "dates": "1399209192000",
    "numbers": "5984"
},
{
    "dates": "1399027545000",
    "numbers": "5985"
}

如果dates数组长度和numbers数组长度不同会发生什么? - Neo-coder
它们始终具有相同的长度。 - corry
dates 数组元素是一个字符串 "[1399518702000, 1399126333000, 1399209192000, 1399027545000]",而不是一个数组。 - chridam
@chirdam,那是个错误,谢谢。 - corry
2个回答

28

从3.2版本开始,您可以在两个数组上使用$unwind$cmp索引并仅匹配相同索引的$match,以完成此操作。

如果您只有示例文档,则此解决方案将填充您编写的内容。如果您有更多文档,则无法确定输出结果。但可以通过按文档的_id进行分组来解决。

db.test.aggregate([
    {
        $unwind: {
            path: '$dates',
            includeArrayIndex: 'dates_index',
        }
    },
    {
        $unwind: {
            path: '$numbers',
            includeArrayIndex: 'numbers_index',
        }
    },
    {
        $project: {
            dates: 1,
            numbers: 1,
            compare: {
                $cmp: ['$dates_index', '$numbers_index']
            }
        }
    },
    {
        $match: {
            compare: 0
        }
    },
    {
        $project: {
            _id: 0,
            dates: 1,
            numbers: 1
        }
    }
])

如果我理解正确,最多可以展开两个数组? - corry
2
@corry 你是怎么理解的?你可以展开任意数量。问题在于每个元素都会变成一个文档,所以对于许多展开,结果将是巨大的数据库。这将非常难以处理,问题是你想要做什么。 - TomG
我认为由于$cmp运算符,无法展开我想要的那么多。我发布了一个关于这个问题的新问题:http://stackoverflow.com/questions/39426022/mongodb-show-children-items-in-one-to-many-relationship - corry

4

Mongo 3.4开始,你可以使用$zip操作符来对数组元素进行配对:

// { values: [23, 2, 14], items: ["aa", "bb", "cc"] }
db.collection.aggregate([

  { $project: { x: { $zip: { inputs: ["$values", "$items"] } } } },
  // { x: [[23, "aa"], [2, "bb"], [14, "cc"]] }

  { $unwind: "$x" },
  // { x: [23, "aa"] }
  // { x: [2,  "bb"] }
  // { x: [14, "cc"] }

  { $project: { value: { $first: "$x" }, item: { $last: "$x" } } }
])
// { value: 23, item: "aa" }
// { value: 2,  item: "bb" }
// { value: 14, item: "cc" }

一旦您的数组经过了$zip处理,只需要在创建数组文档之前对其进行$unwind即可({ value: { $first: "$x" }, item: { $last: "$x" } })。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接