Изменить массив, который хранится в коллекции и экспортировать в CSV

1

У меня есть коллекция Facebook Likes (под названием pagelikes), которая хранится в файле Mongo database/JSON. Ниже приведен пример одной записи.

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

id= уникальный идентификатор страницы Facebook, name= имя страницы в 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 довольно большой (4 ГБ), содержит более 120 тыс. Пользователей, и нет ограничений на количество записей.

Я пробовал и терпел неудачу с mongoexport, хотя структура агрегации кажется наиболее полезной (возможно, функция проекта и разматывания). Тем не менее, у меня мало опыта с Монго.

Любые советы, примеры или предложения были бы очень полезными.

Большое спасибо,

р

Теги:
csv
mongodb-query
aggregation-framework

1 ответ

1
Лучший ответ

Вы можете справиться с этим несколькими способами.

Во-первых, если у вас имеется доступ к MongoDB 3.4, вы можете использовать "Вид", чтобы представить коллекцию с содержимым массива "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 что и выше, так как это также коллекция, доступная для этого.

Если вы действительно не хотите создавать "View" или "другую коллекцию", вы можете просто отправить короткий скрипт в оболочку mongo. Хотя и очень хакерским способом:

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

Обратите также внимание на то, что если вы хотите или "нуждаетесь" в другом разделителе, кроме запятой , здесь один из двух последних подходов с оболочкой, вероятно, является способом выхода. Поскольку это "запланировано" для добавления в mongoexport и mongoimport с TOOLS-87, но, разумеется, "еще предстоит решить". Поэтому, если вам нужен другой выход, тогда вы делаете это сами.

  • 0
    Спасибо, Нил, это сработало абсолютно идеально.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню