Агрегирование MongoDB с поиском и сортировкой с использованием связанных полей коллекции замедляет запрос - PullRequest
2 голосов
/ 04 февраля 2020

У меня есть две коллекции в моей базе данных mongodb:

employee_details с приблизительно 330000 документами, в которых Department_id как справка из коллекции отделов

отделов коллекции с 2 полями _id и имя_экспорта

Я добавил индекс к коллекциям следующим образом:

db.departments.createIndex( { dept_name: 1 } )
db.employee_details.createIndex( { department_id: 1 } )
db.employee_details.createIndex( { employee_fname: 1 } )

Я хочу получить данные для перечисления в таблицу данных, соединив две коллекции. Но когда я попытался сделать это, я столкнулся с двумя проблемами.

Во-первых, когда я добавляю сортировку после поиска, выполнение запроса занимает много времени, я добавлял сортировку после поиска, так как мне нужно сортировать с помощью dept_name of collection ведомства. Запрос дается ниже

db.getCollection("employee_details").aggregate([
  {
    $lookup: {
      from: "departments",
      localField: "department_id",
      foreignField: "_id",
      as: "Department"
    }
  },
  { $unwind: { path: "$Department", preserveNullAndEmptyArrays: true } },
  { $sort: { "Department.dept_name": 1 } },
  { $limit: 30 }
]);

Во-вторых, когда я добавляю поиск выше, запрос становится быстрым, но результат дает неправильную сортировку, если я сортирую, используя dept_name или Department_id (сортировка работает отлично для полей коллекции employee_details ). Запрос приведен ниже

db.getCollection("employee_details").aggregate([
  { $unwind: { path: "$Department", preserveNullAndEmptyArrays: true } },
  { $sort: { "Department.dept_name": 1 } },
  //{ $sort: { "department_id": 1 } }, // tried this also
  { $limit: 30 },
  {
    $lookup: {
      from: "departments",
      localField: "department_id",
      foreignField: "_id",
      as: "Department"
    }
  }
]);

Может кто-нибудь дать оптимизированное решение для извлечения данных вместе с сортировкой из всех связанных коллекций. Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 04 февраля 2020

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

db.departments.aggregate([
  {
    $sort: {
      "dept_name": 1
    }
  },
  {
    $lookup: {
      from: "employee_details",
      localField: "_id",
      foreignField: "department_id",
      as: "Employee"
    }
  },
  {
    $unwind: "$Employee"
  },
  {
    $addFields: {
      tmp: {
        $mergeObjects: [
          {
            Department: "$$ROOT"
          },
          "$Employee"
        ]
      }
    }
  },
  {
    $project: {
      "tmp.Department.Employee": 0
    }
  },
  {
    $addFields: {
      "tmp.Department": [
        "$tmp.Department"
      ]
    }
  },
  {
    $replaceRoot: {
      newRoot: "$tmp"
    }
  },
  {
    $limit: 30
  }
])

MongoPlayground

1 голос
/ 05 февраля 2020

Вы можете использовать следующую агрегацию:

db.getCollection("departments").aggregate([
    {
        $sort: {
            "dept_name": 1
        }
    },
    {
        $lookup: {
            from: "employee_details",
            localField: "_id",
            foreignField: "department_id",
            as: "employees"
        }
    },
    {
        $unwind: "$employees"
    },
    {
        $limit: 30
    },
    { $addFields: { "employees.department_name": "$dept_name" } },
    { $replaceRoot: { newRoot: "$employees" } }
])

Это будет работать для MongoDB версии 3.4, это будет достаточно быстро даже без каких-либо индексов.

...