Нажмите на массив второго уровня в mongodb с узлом / экспресс
Я работаю в чате, где пользователи могут общаться друг с другом на основе отфильтрованных проектов. Пользователи из одного проекта могут общаться друг с другом.
Вот моя модель чата, где каждый документ основан на ref проекта и имеет массив для сообщений с пользовательской ссылкой:
'use strict';
var mongoose = require('bluebird').promisifyAll(require('mongoose'));
var ChatSchema = new mongoose.Schema({
projectid: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Project'
},
messages: [{
userid: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
message: String,
date: {
type: Date,
default: Date.now
},
time: String
}]
});
export default mongoose.model('Chat', ChatSchema);
Сейчас я пытаюсь обновить массив сообщений новыми сообщениями, но я не могу сделать это с последних нескольких часов. Вот что у меня так далеко.
Чтобы получать сообщения чата на основе проектов, которые я использую:
маршруты:
router.get('/projectid/:id', controller.showByProject);
router.post('/projectid/:id', controller.insertMessageByProject);
контроллер:
// Gets the chat thread based on project id
export function showByProject(req, res) {
Chat.findAsync({projectid: req.params.id})
.then(handleEntityNotFound(res))
.then(respondWithResult(res))
.catch(handleError(res));
}
// Insert a new message in the chat based on projectid
export function insertMessageByProject(req, res) {
if (req.body._id) {
delete req.body._id;
}
Chat.findAsync({projectid: req.params.id})
.then(handleEntityNotFound(res))
.then(saveUpdates({$push: {messages: req.body}}))
.then(respondWithResult(res))
.catch(handleError(res));
}
Объект Json, который я отправляю от POSTMAN:
{
"messages":
{
"userid": "56d7967745ab81322a964927",
"message": "This is a meesage"
}
}
ИЛИ ЖЕ
{
"userid": "56d7967745ab81322a964927",
"message": "This is a meesage"
}
Я могу обновить объект, если у меня есть идентификатор объекта для самого документа чата, но внутри моего приложения у меня нет прямой ссылки. Я пробовал также несколько других способов, но каждый раз, когда мое приложение возвращает ошибку 500.
Ваша помощь будет высоко ценится.
РЕДАКТИРОВАТЬ 1: вот вспомогательные функции, которые я использую, сгенерированные угловым полнофункциональным плагином.
function respondWithResult(res, statusCode) {
statusCode = statusCode || 200;
return function(entity) {
if (entity) {
res.status(statusCode).json(entity);
}
};
}
function saveUpdates(updates) {
return function(entity) {
var updated = _.merge(entity, updates);
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}
function removeEntity(res) {
return function(entity) {
if (entity) {
return entity.removeAsync()
.then(() => {
res.status(204).end();
});
}
};
}
function handleEntityNotFound(res) {
return function(entity) {
if (!entity) {
res.status(404).end();
return null;
}
return entity;
};
}
function handleError(res, statusCode) {
statusCode = statusCode || 500;
return function(err) {
res.status(statusCode).send(err);
};
}
РЕДАКТИРОВАТЬ 2: Как я уже упоминал в комментариях, проблема была с _.Merge
функция, которая не сливала объект правильно, хотя должна была иметь возможность обновить объект.
Поэтому я написал свою собственную функцию для saveUpdates следующим образом:
function saveUpdatesForNewChat(updates) {
return function(entity) {
var temp = entity;
temp[0].messages.push(updates);
console.log('\ntemp:');
console.log(require('util').inspect(temp, { depth: null }));
console.log('\nend of ops\n\n');
var updated = _.merge(entity, temp);
console.log('out of merge');
console.log(require('util').inspect(updated, { depth: null }));
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}
Итак, я оставил внутри консольные журналы, и это идеальный объект для сохранения в базе данных, но сервер все равно возвращает 500 ошибок при обновлении.
1 ответ
ХОРОШО! Так что я нашел ответ сам.
Проблема состояла в том, что возвращенный объект был набором результатов, и я вызывал save для всего набора результатов. Я извлек первый элемент из возвращенного набора результатов, вставил новое сообщение в элемент и вызвал для него команду save, и он начал работать.
Вот код:
function saveUpdatesForNewChat(updates) {
return function(entity) {
var temp = entity[0];
temp.messages.push(updates);
var updated = temp;
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}