重塑存储在集合中并导出为CSV的数组

时间:2017-07-04 18:02:47

标签: javascript mongodb csv mongodb-query aggregation-framework

我有一个存储在Mongo数据库/ JSON文件中的Facebook Page Likes(标题为 pagelikes )的集合。以下是一个条目的示例。

{
    "_id" : ObjectId("4725bf8731b8faf4c04595bb"),
    "user_id" : "0939bf9w9804842f9f817ad100",
    "page_likes" : [ 
        {
            "id" : "859302873383",
            "name" : "Hotdogs"
        }, 
        {
            "id" : "8593683902",
            "name" : "Video Games"
        }, 
        {
            "id" : "849204859849028",
            "name" : "Road Bikes"
        }
    ]
}

id =唯一的Facebook页面标识符,名称 = Facebook页面的名称。

我想将整个集合导出为CSV文件,其中包含三列 user_id page_likes.id page_likes.name 。它看起来如下:

user_id                     page_likes.id     page_likes.name
0939bf9w9804842f9f817ad100  859302873383      Hotdogs
0939bf9w9804842f9f817ad100  8593683902        Video Games
0939bf9w9804842f9f817ad100  849204859849028   Road Bikes
...                         ...               ...

JSON文件非常大(4GB),包含超过120K的用户,并且条目的数量没有限制。

我尝试使用mongoexport失败了,尽管聚合框架似乎最有用(可能是项目和展开函数)。也就是说,我对Mongo的经验不多。

任何建议,示例或建议都会非常有帮助。

非常感谢,

[R

1 个答案:

答案 0 :(得分:1)

你可以通过多种方式解决这个问题。

首先,如果您有MongoDB 3.4可用,那么您可以使用"View"来表示数组内容为“un-wound”的集合。 “视图”基本上是一个聚合管道语句,就大多数使用集合的操作而言,它似乎是一个普通的集合。

因此假设您的源集合在此处被称为"pages",那么您将使用以下命令创建“视图”:

db.createView("pageArray", "pages", [{ "$unwind": "$page_likes" }])

然后您可以正常查询集合:

db.pageArray.find()

/* 1 */
{
    "_id" : ObjectId("4725bf8731b8faf4c04595bb"),
    "user_id" : "0939bf9w9804842f9f817ad100",
    "page_likes" : {
        "id" : "859302873383",
        "name" : "Hotdogs"
    }
}

/* 2 */
{
    "_id" : ObjectId("4725bf8731b8faf4c04595bb"),
    "user_id" : "0939bf9w9804842f9f817ad100",
    "page_likes" : {
        "id" : "8593683902",
        "name" : "Video Games"
    }
}

/* 3 */
{
    "_id" : ObjectId("4725bf8731b8faf4c04595bb"),
    "user_id" : "0939bf9w9804842f9f817ad100",
    "page_likes" : {
        "id" : "849204859849028",
        "name" : "Road Bikes"
    }
}

然后发出mongoexport,好像它是一个普通的集合:

mongoexport -d test -c pageArray --type=csv --fields user_id,page_likes.id,page_likes.name
2017-07-05T13:14:11.588+1000    connected to: localhost
user_id,page_likes.id,page_likes.name
0939bf9w9804842f9f817ad100,859302873383,Hotdogs
0939bf9w9804842f9f817ad100,8593683902,Video Games
0939bf9w9804842f9f817ad100,849204859849028,Road Bikes
2017-07-05T13:14:11.589+1000    exported 3 records

当然,添加--out或标准重定向以实际输出到文件。

如果您的MongoDB是旧版本但至少有$out可用(来自MongoDB 2.6),那么请写入另一个集合:

db.pages.aggregate([
  { "$unwind": "$page_likes" },
  { "$project": { "_id": 0 } },
  { "$out": "pagesArray" }
])

然后你基本上运行与上面相同的mongoexport,因为它也是一个可以访问的集合。

如果您真的不想创建“视图”或“其他集合”,那么您只需向mongo shell发送一个简短的脚本即可。虽然是一种非常黑客的方式:

mongo --quiet --eval '
    print("user_id,page_likes.id,page_likes.name");
    db.pages.aggregate([ 
      { "$unwind": "$page_likes" },
      { "$project": { "_id": 0 } },
    ]).forEach(p => print(`${p.user_id},${p.page_likes.id},${p.page_likes.name}`))'

甚至根本没有aggregate()$unwind

mongo --quiet --eval '
    print("user_id,page_likes.id,page_likes.name");
    db.pages.find({},{ _id: 0 }).forEach(p =>
       p.page_likes.forEach(l => print(`${p.user_id},${l.id},${l.name}`)))'

它为您提供相同的输出:

user_id,page_likes.id,page_likes.name
0939bf9w9804842f9f817ad100,859302873383,Hotdogs
0939bf9w9804842f9f817ad100,8593683902,Video Games
0939bf9w9804842f9f817ad100,849204859849028,Road Bikes

另请注意,如果您想要或“需要”不同于逗号,的分隔符,那么最后两种方法中的任何一种都可能是最佳方法。由于这是“预定”添加到mongoexportmongoimport TOOLS-87,但当然是“尚待解决”。所以如果你想要不同的输出,那么你自己做。