使用 node/express 推送到 mongodb 中的二级数组
Push to second level array in mongodb with node/express
我正在开发一个聊天室,用户可以在其中根据项目过滤彼此聊天。来自同一项目的用户可以互相交谈。
这是我的聊天模型,其中每个文档都基于项目引用,并且有一个包含用户引用消息的数组:
'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"
}
如果我有聊天文档本身的对象 ID,我可以更新对象,但在我的应用程序中,我没有直接引用。我也尝试了其他几种方法,但每次我的应用程序 returns 出现 500 错误。
非常感谢您的帮助。
编辑 1:这是我正在使用的由 angular 全栈插件生成的帮助功能。
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;
});
};
}
好的,所以我将控制台日志留在里面,它是保存到数据库中的完美对象,但服务器仍然 returns 更新时出现 500 错误。
好的!所以我自己找到了答案。
问题是返回的对象是一个结果集,而我正在对整个结果集调用保存。我从返回的结果集中提取了第一个元素,将新消息推送到该元素并在其上调用保存并开始工作。
代码如下:
function saveUpdatesForNewChat(updates) {
return function(entity) {
var temp = entity[0];
temp.messages.push(updates);
var updated = temp;
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}
我正在开发一个聊天室,用户可以在其中根据项目过滤彼此聊天。来自同一项目的用户可以互相交谈。
这是我的聊天模型,其中每个文档都基于项目引用,并且有一个包含用户引用消息的数组:
'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"
}
如果我有聊天文档本身的对象 ID,我可以更新对象,但在我的应用程序中,我没有直接引用。我也尝试了其他几种方法,但每次我的应用程序 returns 出现 500 错误。
非常感谢您的帮助。
编辑 1:这是我正在使用的由 angular 全栈插件生成的帮助功能。
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;
});
};
}
好的,所以我将控制台日志留在里面,它是保存到数据库中的完美对象,但服务器仍然 returns 更新时出现 500 错误。
好的!所以我自己找到了答案。
问题是返回的对象是一个结果集,而我正在对整个结果集调用保存。我从返回的结果集中提取了第一个元素,将新消息推送到该元素并在其上调用保存并开始工作。
代码如下:
function saveUpdatesForNewChat(updates) {
return function(entity) {
var temp = entity[0];
temp.messages.push(updates);
var updated = temp;
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}