Фильтрация коллекции mongodb занимает много времени, чтобы выполнить - PullRequest
0 голосов
/ 31 января 2020

Я пытаюсь отфильтровать 2 коллекции, которые содержат более 30000 данных. Фильтрация коллекции A выполняется быстро, но на основе значения коллекции A. Я фильтрую коллекцию B, которая отнимает много времени, но мне нужны более поздние данные из коллекции B. Я могу фильтровать, но выполнение занимает слишком много времени.

Вот код

packageA.aggregate([
      { "$match": { "Family": { "$in": req.body.text } } },  //array of   
      {
        $lookup:
        {
          from: "lic",
          localField: "ProLic",
          foreignField: "ID",
          as: "subLic"
        }
      },
      {
        $project: {
          prodName: "$proName"
        }
      }
    ])
      .then(product => {   // from here its taking time to filter 
        var result = [];
        product.forEach(comp => {
          result.push(
            new Promise((resolve, reject) => {
              packageB.find({ "name": comp.proName})
                .sort({ "date": -1 })        //I need the latest update data
                .limit(1)
                .exec((err, docs) => {
                  if (err) return reject(err)
                  resolve(docs)
                })
            })
          )
        })
        Promise.all(result).then(ele => {
          var final = [];
          ele.forEach(ss => {
            if (ss[0]) {
              final.push(ss[0]);
            }
          })
          let fal = _.uniq(final, 'product_name')
          res.status(200).json({
            data: fal            //here is the final value
          })
        })
      })

, есть ли лучший способ сократить время выполнения. пожалуйста, помогите мне с этим

1 Ответ

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

Конечно, это будет отложено. Вы перебираете массив и делаете отдельный вызов БД для каждого proName - вы можете избежать всего этого сетевого трафика c, объединив приведенный ниже запрос с первоначальным совокупным запросом. через $lookup. Иметь правильные индексы для каждого поля, упомянутого в запросе, и пусть db возьмет на себя все остальное. Работа с данными размером 30 КБ не должна быть проблемой при правильной индексации.

packageB.find({ "name": comp.proName})
                .sort({ "date": -1 })        //I need the latest update data
                .limit(1)

Попробуйте это:

let result = await packageA.aggregate([
    { "$match": { "Family": { "$in": req.body.text } } },  
    {
        $lookup:
        {
            from: "lic",
            localField: "ProLic",
            foreignField: "ID",
            as: "subLic"
        }
    },
    {
        $project: {
            prodName: "$proName"
        }
    }, {
        $lookup:
        {
            from: "packageB",
            localField: "prodName",
            foreignField: "name",
            as: "packageBDocs"
        }
    }, { $unwind: '$packageBDocs' }, { $sort: { date: -1 } },
    { $group: { _id: '$_id', data: { $first: '$$ROOT' } } },
    { $replaceRoot: { newRoot: '$data' } }
])

Promise.all(result).then(ele => {
    var final = [];
    ele.forEach(ss => {
        if (ss[0]) {
            final.push(ss[0]);
        }
    })
    let fal = _.uniq(final, 'product_name')
    res.status(200).json({
        data: fal            //here is the final value
    })
})
    })

Из этого: { "name": comp.proName} - У вас есть несколько документов в коллекции packageB с одним и тем же именем, но с другим date? Если да, есть два варианта, один из которых находится над запросом, или же как другой вариант из вышеуказанного запроса, вы можете избежать всех этапов, начинающихся с $unwind, если считаете, что поле date является правильной датой, которая создается при вставке документов в packageB коллекция. Как и в $lookup массив stage packageBDocs будет иметь документы в порядке соответствия документов, вставленных в коллекцию packageB. Таким образом, после этапа $lookup вы можете просто выполнить {$addFields : {packageBDocs: { $arrayElemAt: [ "$packageBDocs", -1 ] }}}, который получит последний документ.

...