$ group после $ lookup занимает слишком много времени - PullRequest
0 голосов
/ 15 мая 2018

У меня есть следующая коллекция монго:

{
    "_id" : "22pTvYLd7azAAPL5T",
    "plate" : "ABC-123",
    "company": "AMZ",
    "_portfolioType" : "account"
},
{
    "_id" : "22pTvYLd7azAAPL5T",
    "plate" : "ABC-123",
    "_portfolioType" : "sale",
    "price": 87.3
},
{
    "_id" : "22pTvYLd7azAAPL5T",
    "plate" : "ABC-123",
    "_portfolioType" : "sale",
    "price": 88.9
}

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

db.getCollection('temp').aggregate([
{
    $lookup: { 
        from: 'temp',
        let: { 'p': '$plate', 't': '$_portfolioType' },
        pipeline: [{
            '$match': {
                '_portfolioType': 'sale',
                '$expr': { '$and': [ 
                    { '$eq': [ '$plate', '$$p'  ] },
                    { '$eq': [ '$$t', 'account'  ] }
                ]}
            }
        }],
        as: 'revenues' 
    },
},
{
    $project: {
        plate: 1,
        company: 1,
        totalTrades: { $arrayElemAt: ['$revenues', 0] },
    },
},

{
    $addFields: {
        revenue: { $add: [{ $multiply: ['$totalTrades.price', 100] }, 99] },
    },
},

{
    $group: {
        _id: '$company',
        revenue: { $sum: '$revenue' },
    }
}
])

Запрос работает нормально, если я удаляю $group stage, однако, как только я добавляю $group stage, mongo начинает бесконечную обработку. Я попытался добавить $match в качестве первого этапа, чтобы ограничить количество обрабатываемых документов, но безуспешно. Например:

{
    $match: { $or: [{ _portfolioType: 'account' }, { _portfolioType: 'sale' }] }
},

Я также пытался использовать { explain: true }, но ничего полезного не получается.

1 Ответ

0 голосов
/ 16 мая 2018

Как заметил Нил Ланн, вам, скорее всего, не нужен поиск, чтобы достичь своей "конечной цели", которая все еще довольно расплывчата.

Пожалуйста, прочитайте комментарии и при необходимости измените:

db.temp.aggregate([
    {$group:{
        // Get unique plates
        _id: "$plate",
        // Not clear what you expect if there are documents with
        // different company, and the same plate.
        // Assuming "it never happens"
        // You may need to $cond it here with {$eq: ["$_portfolioType", "account"]}
        // but you never voiced it.         
        company: {$first:"$company"},
        // Not exactly all documents with _portfolioType: sale,
        // but rather price from all documents for this plate.
        // Assuming price field is available only in documents 
        // with "_portfolioType" : "sale". Otherwise add a $cond here.
        // If you really need "all documents", push $$ROOT instead.
        prices: {$push: "$price"}        
    }},
    {$project: {
       company: 1,
       // Apply your math here, or on the previous stage
       // to calculate revenue per plate
       revenue: "$prices" 
    }}
    {$group: {
        // Get document for each "company" 
        _id: "$company",
        // Revenue associated with plate
        revenuePerPlate: {$push: {"k":"$_id", "v":"$revenue"}}        
    }},
    {$project:{         
        _id: 0,
        company: "$_id",
        // Count of unique plate
        platesCnt: {$size: "$revenuePerPlate"},
        // arrayToObject if you wish plate names as properties
        revenuePerPlate: {$arrayToObject: "$revenuePerPlate"}
    }}
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...