MongoDB - объединение двух результатов запросов и density_rank - PullRequest
0 голосов
/ 22 января 2020

Я изучаю MongoDB, и у меня есть некоторые проблемы с пониманием его концепции.

У меня есть коллекция, которая выглядит так:

db.email.findOne()
{
        "_id" : ObjectId("52af48b5d55148fa0c199646"),
        "sender" : "tori.wells@enron.com",
        "recipients" : [
                "michael@optsevents.com"
        ],
        "cc" : [ ],
        "text" : "Mr. Christman:\n\nThank you for your invitation for Dr. Lay to speak at your upcoming forum in \nFrance, the format looks wonderful.  Unfortunately, Dr. Lay has calendar \nconflicts and will be unable to participate.\n\nIf you should need further assistance, please do not hesitate to contact us.\n\nTori Wells\nExecutive Assistant",
        "mid" : "22263156.1075840285610.JavaMail.evans@thyme",
        "fpath" : "enron_mail_20110402/maildir/lay-k/_sent/101.",
        "bcc" : [ ],
        "to" : [
                "michael@optsevents.com"
        ],
        "replyto" : null,
        "ctype" : "text/plain; charset=us-ascii",
        "fname" : "101.",
        "date" : "2000-08-04 09:04:00-07:00",
        "folder" : "_sent",
        "subject" : "Wall Street Journal Millennium Forum"
}

Это база данных Enron.

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

Мне удалось сделать два запроса, которые выглядят так:

db.email.aggregate({$group:{_id:"$sender",SendsAmount:{$sum:1}}},{$sort:{SendsAmount:-1}})
{ "_id" : "rosalee.fleming@enron.com", "SendsAmount" : 849 }
{ "_id" : "brown_mary_jo@lilly.com", "SendsAmount" : 82 }
{ "_id" : "leonardo.pacheco@enron.com", "SendsAmount" : 78 }

db.email.aggregate({$group:{_id:"$recipients",ReceivedAmount:{$sum:1}}},{$unwind:"$_id"},{$sort:{ReceivedAmount:-1}})
{ "_id" : "klay@enron.com", "ReceivedAmount" : 1350 }
{ "_id" : "kenneth.lay@enron.com", "ReceivedAmount" : 912 }
{ "_id" : "kenneth.lay@enron.com", "ReceivedAmount" : 78 }

Как видите, первый возвращает мне электронные письма и количество отправленных с него электронных писем, а второй также возвращает электронные письма и количество полученных им писем.

Моя точка зрения заключается в том, чтобы присоединиться ?) эти два в один и получают один запрос, который будет возвращать что-то вроде:

{ "_id" : "email@enron.com", "SendsAmount" : 57, "ReceivedAmount": 43 }

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

--- Моя вторая проблема - попытка создать какой-нибудь DENSE_RANK, которого нет в MongoDB. Я хочу ранжировать адреса электронной почты по количеству отправленных писем.

Я использовал $ unwind и insertArrayIndex, но получил что-то вроде ROW_NUMBER, которого я не ищу.

Я написал что-то вроде этого:

db.email.aggregate({$group:{"_id":"$sender",SendsAmount:{$sum:1},rank:0}},{$sort:{"ile":-1}}).forEach(function(x){
                        var howmany=0;
                        var query=db.email.aggregate({$group:{"_id":"$sender",SendsAmount:{$sum:1}}},{$match:{ile:{$gt:x.SendsAmount}}},{$group:{_id:null, HowManyGreater:{$sum:1}}});
                        query.forEach(function(y){
                            howmany=y.HowManyGreater;
                        }); 
                        howmany=howmany+1;
                        print("email: "+ x._id + " SendsAmount: " + x.SendsAmount + " rank " + howmany+1);
                    });

Это дает мне желаемый результат, но это даже не документ, а только печатная информация. Я читал о MapReduce, но не понял, как его использовать в этом случае.

1 Ответ

0 голосов
/ 22 января 2020

Если вы хотите выполнить все вычисления в агрегированном запросе, вы можете использовать этапы $ facet и $ group, как показано ниже

db.email.aggregate([
  {
    $facet: {
      send: [
        {
          $group: {
            _id: "$sender",
            SendsAmount: {
              $sum: 1
            }
          }
        },
        {
          $sort: {
            SendsAmount: -1
          }
        }
      ],
      recieve: [
        {
          $group: {
            _id: "$recipients",
            ReceivedAmount: {
              $sum: 1
            }
          }
        },
        {
          $unwind: "$_id"
        },
        {
          $sort: {
            ReceivedAmount: -1
          }
        }
      ]
    }
  },
  {
    $project: {
      all: {
        $concatArrays: [
          "$recieve",
          "$send"
        ]
      }
    }
  },
  {
    $unwind: "$all"
  },
  {
    $group: {
      _id: "$all._id",
      ReceivedAmount: {
        $sum: {
          $cond: {
            if: {
              $gt: [
                "$all.ReceivedAmount",
                null
              ]
            },
            then: "$all.ReceivedAmount",
            else: 0
          }
        }
      },
      SendsAmount: {
        $sum: {
          $cond: {
            if: {
              $gt: [
                "$all.SendsAmount",
                null
              ]
            },
            then: "$all.SendsAmount",
            else: 0
          }
        }
      }
    }
  }
])
...