Mongo提供了针对大型数据集拆分文档数组的功能吗?

4
类似于map/reduce但是反过来。Mongo有一种重新格式化数据的方式吗?我有一个按照以下格式排列的集合。
{ 
  {"token-id" : "LKJ8_lkjsd"
    "data": [
               {"views":100, "Date": "2015-01-01"},
               {"views":200, "Date": "2015-01-02"},
               {"views":300, "Date": "2015-01-03"},
               {"views":300, "Date": "2015-01-03"}
            ]
  }
}

我希望将整个集合处理为新格式,在这个格式中,每个时间序列数据点都是其文档,使用一些内在的Mongo功能类似于map reduce映射到ID。如果没有,我希望我们可以想出一个策略来实现此目标。

{
  { "token-id" : "LKJ8_lkjsd", "views": 100, "Date" : "2015-01-01"},
  { "token-id" : "LKJ8_lkjsd", "views": 200, "Date" : "2015-01-01"},
  { "token-id" : "LKJ8_lkjsd", "views": 300, "Date" : "2015-01-01"}
}

也许这可以帮助你:https://dev59.com/omYr5IYBdhLWcg3w7uZx - mvw
3个回答

3
你需要使用聚合管道中的$unwind,可参考MongoDB文档
在你的情况下,代码如下:
db.yourcollection.aggregate( [ { $unwind : "$data" } ] )

unwind 不会自动将文档插入到新集合中。

您可以使用

> db.test.aggregate( [ { $unwind : "$data" }, {$project: {_id:0, "token-id":1, "data":1}}, {$out: "another"} ] )
> db.another.find()

在第一行中,您需要禁止_id,因为在$unwind之后,您将获得具有相同_id的4个文档(因此它们无法插入) 没有明确的_id,新值将自动生成。
这是我根据您的示例得到的输出。
{ "_id" : ObjectId("560599b1699289a5b754fab9"), "token-id" : "LKJ8_lkjsd", "data" : { "views" : 100, "Date" : "2015-01-01" } }
{ "_id" : ObjectId("560599b1699289a5b754faba"), "token-id" : "LKJ8_lkjsd", "data" : { "views" : 200, "Date" : "2015-01-02" } }
{ "_id" : ObjectId("560599b1699289a5b754fabb"), "token-id" : "LKJ8_lkjsd", "data" : { "views" : 300, "Date" : "2015-01-03" } }
{ "_id" : ObjectId("560599b1699289a5b754fabc"), "token-id" : "LKJ8_lkjsd", "data" : { "views" : 300, "Date" : "2015-01-03" } }

这个功能可以实现,但只会得到一个单一的文档结果,而不是一个新的集合。此外,Mongo为此操作分配的大小仅为16MB。我的数据库已经达到了10GB。 - Dap

3

aggregate命令可以返回游标或将结果存储在集合中,这些结果不受大小限制。db.collection.aggregate()返回一个游标,并且可以返回任意大小的结果集。

 var result = db.test.aggregate( [ { $unwind : "$data" }, {$project: {_id:0, "token-id":1, "data":1}}])

    for(result.hasNext()){
     db.collection.insert(result.next());
    }

3
根据您的问题,如果数据量很大,那么使用$unwind会导致查询速度变慢。对于这种情况,您应该在聚合中使用$map来处理data数组,如下所示:
db.collection.aggregate({
"$project": {
    "result": {
        "$map": {
            "input": "$data",
            "as": "el",
            "in": {
                "token-id": "$token-id",
                "views": "$$el.views",
                "Date": "$$el.Date"
            }
        }
    }
 }
}).pretty()

1
不幸的是,这只重新映射每个项目,并没有为每个数据记录创建附加文档。 - Dap
@Dap,我不明白你期望的输出是什么,但也许你应该“展开”result,这样你就可以得到单独的文档。 - Neo-coder
感谢您的回复。是的,我正在寻找一个没有限制的取消操作,但除了其16MB的限制。 - Dap
1
@Dap,我看到你已经得到了答案,但是仍然存在问题,即您需要展开数据并迭代以将其插入新集合中,因此更好的方法是在聚合中展开并使用$out - Neo-coder

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