Вопрос или проблема
Как мне отсортировать ответ из таблицы по ключу другой таблицы?
Например:
У меня есть таблица с данными пользователей. Содержимое таблицы:
{ _id:objectId, name:string, age:number}
Теперь у меня есть другая таблица с данными зарплат сотрудников. Содержимое таблицы:
{ _id:objectId userId:objectId //ссылка на пользователя totalSalary:number}
Что я хочу здесь, так это то, что когда я получаю данные из зарплаты сотрудников, я хочу отсортировать результат по имени пользователя (которое находится в таблице пользователей) или по totalSalary (в зависимости от того, что пользователь введет в порядке, упомянутом этим пользователем)
Я использую mongoose 8.4.5, если есть какой-либо запрос, который я могу использовать в mongoose, пожалуйста, дайте мне знать. Если вы предпочитаете агрегатный поток, пожалуйста, дайте мне пример кода, так как я новичок в агрегатных потоках.
Ответ или решение
Кросс-табличная сортировка в MongoDB с помощью Mongoose
Вопрос о сортировке данных в MongoDB, когда требуется объединить информацию из различных коллекций (таблиц), часто возникает у разработчиков. В вашем случае вы хотите отсортировать данные о зарплатах сотрудников, основываясь на имени пользователя или его зарплате. Это можно реализовать с помощью агрегатных операций в Mongoose.
Структура данных
Вы описали две коллекции в MongoDB:
-
Коллекция "user data":
{ _id: ObjectId, name: String, age: Number }
-
Коллекция "employee salary data":
{ _id: ObjectId, userId: ObjectId, // ссылка на пользователя totalSalary: Number }
Для того, чтобы производить сортировку, вам необходимо будет использовать агрегацию, которая позволит объединить данные из обеих коллекций.
Пример кода с использованием агрегатного конвейера
Вот пример кода, который можно использовать в вашем приложении на Mongoose версии 8.4.5. В этом примере мы будем сортировать результаты по имени пользователя или общей зарплате в зависимости от пользовательского ввода.
const mongoose = require('mongoose');
// Ваши модели
const User = mongoose.model('User', new mongoose.Schema({
name: String,
age: Number
}));
const EmployeeSalary = mongoose.model('EmployeeSalary', new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
totalSalary: Number
}));
// Функция для получения и сортировки данных
async function getSortedSalaries(sortBy) {
try {
const salaries = await EmployeeSalary.aggregate([
{
$lookup: {
from: 'users', // называйте коллекции в нижнем регистре
localField: 'userId',
foreignField: '_id',
as: 'userInfo'
}
},
{
$unwind: { path: '$userInfo', preserveNullAndEmptyArrays: true } // Разворачиваем массив
},
{
$project: {
_id: 1,
userId: 1,
totalSalary: 1,
userName: '$userInfo.name'
}
},
{
$sort: {
[sortBy === 'name' ? 'userName' : 'totalSalary']: 1 // Сортировка по имени пользователя или общей зарплате
}
}
]);
return salaries;
} catch (error) {
console.error('Ошибка получения данных:', error);
throw error; // можно обработать ошибку как необходимо
}
}
Объяснение кода
-
$lookup: Этот оператор объединяет данные из коллекции "employee salary data" с коллекцией "user data". Мы указываем, что поле
userId
должно соответствовать_id
из "user data". -
$unwind: Этот оператор используется, чтобы разворачивать массив
userInfo
, созданный оператором$lookup
, в отдельные документы. Это помогает получить удобный доступ к атрибутам пользователя для сортировки и отображения. -
$project: Мы выбираем необходимые поля для конечного результата. Здесь мы создаем поле
userName
, которое будет содержать имя пользователя. -
$sort: В этом этапе данные сортируются по выбранному критериям: либо по имени пользователя, либо по общей зарплате.
Заключение
С помощью описанного метода вы можете гибко обрабатывать запросы на сортировку данных в MongoDB с использованием Mongoose. Подход через агрегатные операции является мощным инструментом, позволяющим не только объединять, но и манипулировать данными на более высоком уровне. Вы можете расширять и адаптировать этот код по мере необходимости для решения более сложных задач анализа данных.