Как объединить документы из разных коллекций в одну с Mongo и структурой агрегации? - PullRequest
0 голосов
/ 02 ноября 2019

В моей базе данных 4 коллекции

(с именами их атрибутов, указанных в скобках):

1. сообщения

(с атрибутами --- CreationDate, PostId, PostTypeId and UserId),

2. пользователи

(с атрибутами --- CreationDate and Id),

3. голосов

(с атрибутами --- CreationDate, Id and UserId)

и

4. комментарии

(с атрибутами --- CreationDate, Id and UserId).

Я хочу создать коллекцию с именем факты , объединяет информацию, содержащуюся в предыдущей таблице.

Это будет коллекция, состоящая из записей, пользователей, голосов и комментариев.

Я имею в виду, что каждый документ сборника фактов может происходить из записей, пользователей, голосов или комментариев сборников.

Структура фактов сбора будет иметь вид:

                                   PostId  | PostTypeId | userId   | VoteId | CommentId
if document comes from posts     | present |  present   | present  |  null  | null     |

if document comes from users     | null    |   null     | present  |  null  | null     |

if document comes from votes     | present |   null     | present  | present | null    |

if document comes from comments  | present |   null     | present  | null    | present |

Как вы видите, это будет очень редкая коллекция (в ней будет многонулевых значений).

Как я могу построить эту коллекцию фактов, используя MongoDB и структуру агрегирования?

Я пытался объединить записи и коллекции пользователей, но он не дал никаких результатов:

respuestas = db.users.aggregate( [
    {'$lookup': {
        'from': "posts", 
        'localField': "Id",
        'foreignField': "OwnerUserId",
        'as': "p"}
    },
    { '$unwind': '$p'},
    {
        "$group": {
            "_id": "$Id",
            "users": {
                "$push": {
                     'CreationDate' : '$CreationDate',
                     'Post' : '',
                     'PostType' : '',
                     'UserId': '$Id',
                     'VoteId' : '',
                     'CommentId' : ''
                }
            },
            "p": {
                "$push": {
                     'CreationDate' : '$p.CreationDate',
                     'Post' : '$p.Id',
                     'PostType' : '$p.PostTypeId',
                     'UserId': '$p.OwnerUserId',
                     'VoteId' : '',
                     'CommentId' : ''
                }
            }
        }
    },
    {'$limit': 20}
    ])

list(respuestas)

1 Ответ

0 голосов
/ 06 ноября 2019

Наконец-то я нашел способ сделать то, что искал. Я публикую решение на случай, если кто-то выиграет от него.

db.users.aggregate( [
        { '$project' : 
         {
             'CreationDate' : '$CreationDate',
             'Post' : '',
             'PostType' : '',
             'UserId': '$Id',
             'VoteId' : '',
             'CommentId' : ''
         }
        },
        {'$out': "StackOverflowFacts"}
        ])

db.votes.aggregate( [
        { '$project' : 
         {
             'CreationDate' : '$CreationDate',
             'Post' : '$PostId',
             'PostType' : '',
             'UserId': '$UserId',
             'VoteId' : '$Id',
             'CommentId' : ''
         }
        },
        {'$merge' : { 'into' : "StackOverflowFacts" } }
        ])

db.comments.aggregate( [
        { '$project' : 
         {
             'CreationDate' : '$CreationDate',
             'Post' : '$PostId',
             'PostType' : '',
             'UserId': '$UserId',
             'VoteId' : '',
             'CommentId' : '$Id'
         }
        },
        {'$merge' : { 'into' : "StackOverflowFacts" } }
        ])

db.posts.aggregate( [
        { '$project' : 
         {
             'CreationDate' : '$CreationDate',
             'Post' : '$Id',
             'PostType' : '$PostTypeId',
             'UserId': '$OwnerUserId',
             'VoteId' : '',
             'CommentId' : ''
         }
        },
        {'$merge' : { 'into' : "StackOverflowFacts" } }
        ])

Как видите, с помощью $out вы можете создать новую коллекцию с выводом запроса. Затем, используя $merge, вы можете добавить содержимое (добавление строк) в созданную коллекцию.

Вы также можете улучшить коллекцию, создав несколько индексов, чтобы быстрее выполнять запросы: используя db.StackOverflowFacts.create_index.

Вы можете визуализировать начало коллекции, выполнив:

list(db.StackOverflowFacts.find().limit( 5 ))
...