Как вернуть результаты Mongoose из метода find?
Проблема с возвращением результатов из нескольких запросов в Mongoose
Я пытаюсь отрендерить страницу с результатами из нескольких запросов к базе данных с использованием Mongoose, но не могу понять, как правильно сделать выборку данных.
В документации я нашел следующий способ, который работает:
users.find({}, function(err, docs){
res.render('profile/profile', {
users: docs
});
});
Однако, я бы хотел вернуть результаты из запросов в более удобном для меня формате, чтобы можно было сделать что-то вроде этого:
var a_users = users.find({}); // не работающий пример
Таким образом, у меня будет возможность получить несколько результатов и использовать их для публикации на странице.
Например, я бы хотел сделать что-то вроде этого:
/* не работающий пример */
var a_users = users.find({});
var a_articles = articles.find({});
res.render('profile/profile', {
users: a_users,
articles: a_articles
});
Есть ли способ сделать это? Заранее спасибо за помощь!
4 ответ(ов)
Вы пытаетесь навязать синхронную парадигму, но это просто не работает. Node.js в основном однопоточный — когда операция ввода-вывода завершена, контекст выполнения возвращается. Управление сигналами осуществляется с помощью колбеков. Это означает, что у вас будут либо вложенные колбеки, именованные функции, либо библиотека управления потоком, чтобы сделать код более читаемым.
Посмотрите на async.parallel:
async.parallel([
function(cb){
users.find({}, cb);
},
function(cb){
articles.find({}, cb);
}
], function(results){
// results содержит как пользователей, так и статьи
});
Следуя этому подходу, вы сможете выполнять несколько асинхронных операций параллельно, а затем обработать результаты, когда все они завершатся. Это значительно улучшит читаемость и структуру вашего кода.
Вы можете использовать функцию freturn
, которую вы предоставили, чтобы обрабатывать результаты без необходимости повторного кода в каждой функции. Вот пример перевода вашего вопроса на русский язык в стиле ответа на StackOverflow:
У вас есть функция, которая используется для возврата результата в функции Node. Вы можете использовать следующую реализацию:
function freturn(value, callback) {
if (callback) {
return callback(value);
}
return value;
}
Кроме того, вы можете добавить необязательный параметр callback
в сигнатуры всех ваших функций. Это позволит вам легко управлять возвратом значений, предоставляя возможность обработать их через коллбэк, если он передан, или просто вернуть значение напрямую:
function exampleFunction(param, callback) {
const result = param * 2; // Пример какой-то логики
return freturn(result, callback);
}
Таким образом, если вы вызовете exampleFunction
с коллбэком, то он будет обработан, а если без него, то функция просто вернет значение.
Обеспечив такой подход, вы сможете избежать дублирования кода и сделать свои функции более удобными для использования.
Я сталкивался с очень похожей проблемой, но использовал socket.io и доступ к базе данных с клиента. Мой метод получения данных из базы возвращал содержимое базы до того, как данные успевали загрузиться. Поэтому я поделюсь своими находками здесь:
Вот моя функция для получения данных из базы:
// Читаем доски - полная база данных
var readBoards = function() {
var callback = function() {
return function(error, data) {
if (error) {
console.log("Ошибка: " + error);
}
console.log("Доски от сервера (функция): " + data);
}
};
return boards.find({}, callback());
};
А вот мой слушатель событий сокета:
socket.on('getBoards', function() {
var query = dbConnection.readBoards();
var promise = query.exec();
promise.then(function(boards) {
socket.emit('onGetBoards', boards);
}).catch(function(err) {
console.log("Ошибка: " + err);
});
});
Чтобы решить проблему, мы используем промисы, которые предоставляет Mongoose, и только после того, как данные получены из базы, я отправляю их обратно на клиент с помощью сокета.
На мой взгляд, это довольно эффективный подход.
Вы можете достичь желаемого результата с помощью следующего кода. Надеюсь, это вам поможет.
var async = require('async');
// пользовательские импорты
var User = require('../models/user');
var Article = require('../models/article');
var List1Objects = User.find({});
var List2Objects = Article.find({});
var resourcesStack = {
usersList: List1Objects.exec.bind(List1Objects),
articlesList: List2Objects.exec.bind(List2Objects),
};
async.parallel(resourcesStack, function (error, resultSet){
if (error) {
res.status(500).send(error);
return;
}
res.render('home', resultSet);
});
MongoParseError: URI отсутствует имя хоста, доменное имя и TLD
Mongoose: Опциональные поля в схеме
Ошибка "npm WARN package.json: Нет поля repository"
Как получить параметры GET после "?" в Express?
Включение HTTPS в express.js