Создать матрицу из документов mongodb - PullRequest
0 голосов
/ 10 октября 2018

Я пытаюсь преобразовать документы mongodb в матричный формат

, например,

для этот ввод

[
  {
    username: "user1",
    result: [
      {
        subId: "sub1",
        marks: 90
      },
      {
        subId: "sub4",
        marks: 92
      },
      {
        subId: "sub3",
        marks: 73
      }
    ]
  },
  {
    username: "user3",
    result: [
      {
        subId: "sub3",
        marks: 87
      },
      {
        subId: "sub5",
        marks: 91
      },
      {
        subId: "sub2",
        marks: 88
      }
    ]
  }
]

вывод долженбыть таким:

        sub1  |  sub2  |  sub3  |  sub4  |  sub5  | 
======|=======|========|========|========|========|
user1 |  90   |        |    73  |        |        |      
user2 |       |        |        |        |        |      
user3 |       |   88   |    87  |        |   91   |  

Я пытался решить эту проблему с помощью агрегата mongodb, панд и numpy библиотеки, но не смог получить желаемый результат.

Не могли бы вы мне предложитьДругой способ заставить это работать.

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

Вы должны преобразовать каждый документ в плоский документ (не вложенный).

Итак, первая запись будет такой:

{'user': 'user1', 'sub1': 90, 'sub4': 92, 'sub3': 73}

Теперь вы можете использовать панд для создания из диктата.

Это полный код:

doc_list = [
    {
        'username': "user1",
        'result': [
            {
                'subId': "sub1",
                'marks': 90
            },
            {
                'subId': "sub4",
                'marks': 92
            },
            {
                'subId': "sub3",
                'marks': 73
            }
        ]
    },
    {
        'username': "user3",
        'result': [
            {
                'subId': "sub3",
                'marks': 87
            },
            {
                'subId': "sub5",
                'marks': 91
            },
            {
                'subId': "sub2",
                'marks': 88
            }
        ]
    }
]

pandas_list = []
for doc in doc_list:
    line = {'user': doc['username']}

    for sub_mark in doc['result']:
        line[sub_mark['subId']] = sub_mark['marks']

    pandas_list.append(line)

df = pd.DataFrame.from_records(pandas_list)
0 голосов
/ 10 октября 2018

Может быть это

db.collection.aggregate([
  { "$unwind": "$result" },
  { "$group": {
    "_id": "$username",
    "data": { "$push": { "k": "$result.subId", "v": "$result.marks" }}
  }},
  { "$addFields": { "data": { "$arrayToObject": "$data" }}},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$data" }}
  }},
  { "$addFields": {
    "data": { "$arrayToObject": "$data" }
  }},
  { "$unwind": "$data" },
  { "$replaceRoot": { "newRoot": "$data" }}
])

Результат

[
  {
    "user1": {
      "sub1": 90,
      "sub3": 73,
      "sub4": 92
    },
    "user3": {
      "sub2": 88,
      "sub3": 87,
      "sub5": 91
    }
  }
]
0 голосов
/ 10 октября 2018

Что-то вроде этого возможно?

db.collection.aggregate({
    $project: {
        "arr": { 
            $reduce: {
                input: {
                    $map: {
                        "input": "$result",
                        "as": "this",
                        "in": {
                            $let: {
                                "vars": {
                                    "tmp": { $objectToArray: "$$this" }
                                },
                                "in": {
                                    $arrayToObject: [[
                                        {
                                            k: { $arrayElemAt: [ "$$tmp.v", 0 ] },
                                            v: { $arrayElemAt: [ "$$tmp.v", 1 ] }
                                        }
                                    ]]
                                }
                            }
                        }
                    }
                },
                "initialValue": { "_id": "$_id" },
                "in": { $mergeObjects: [ "$$value", "$$this" ] }
            }
        }
    }
}, {
    $replaceRoot: {
        "newRoot": "$arr"
    }
})

Результат будет:

/* 1 */
{
    "_id" : ObjectId("5bbe443ef68f12cf65d17b14"),
    "sub1" : 90,
    "sub4" : 92,
    "sub3" : 73
}

/* 2 */
{
    "_id" : ObjectId("5bbe443ef68f12cf65d17b16"),
    "sub3" : 87,
    "sub5" : 91,
    "sub2" : 88
}
...