我正在使用Nodejs和Mongo创建一个REST API。我对 Node 很陌生,除了更新所有用户之外,我能够执行所有其他请求,例如 GET,POST,DELETE,PUT(针对单个用户)。
我想更新所有用户数据。以下是我的代码。
import mongoose from 'mongoose';
import { Router } from 'express';
import User from '../model/user';
import bodyParser from 'body-parser';
export default({ config, db }) => {
let api = Router();
api.put('/', (req, res) => {
User.find({}, (err, user) => {
if (err) {
res.send(err);
}
user.name = req.body.name;
user.salary = req.body.salary;
user.save(function(err) {
if (err) {
res.send(err);
}
res.json({ message: 'All User info updated' });
});
});
});
return api;
}
我得到user.save
在提出放置请求时不是一个函数。我在堆栈溢出上浏览了所有关于这个问题的问题,但这对我来说非常令人困惑。
你可以这样做。在此处查看猫鼬的文档更新功能 http://mongoosejs.com/docs/documents.html
import mongoose from 'mongoose';
import {
Router
} from 'express';
import User from '../model/user';
import bodyParser from 'body-parser';
export default ({
config,
db
}) => {
let api = Router();
api.put('/', (req, res) => {
User.update({}, {
name: req.body.name,
salary: req.body.salary
}, {
multi: true
}, (err, data) => {
if (err) {
res.send(err);
}
res.json({
message: 'All User info updated'
});
});
});
return api;
}
您面临的问题是由于find
方法的返回类型,或者我会说查询。
mongo 中的find
返回一个cursor
(它是一个迭代器并包含查询结果的东西),它在mongoose
中的实现会给你一个文档数组。
因此,无论您的数据库只有一个用户还是多个用户,User.find({})
总是会返回一个数组(空数组或包含文档的数组)。而且由于.save()
方法仅在有效的猫鼬模型上可用,因此数组(查询结果)不是,因此您user.save is not a function.
出现该错误
尝试记录在回调中的查找查询后获得的用户,您将获得一个数组。
可能的解决方案
1.完全不推荐
迭代用户(我会说用户),你进入你的回调,然后在每个用户的每次迭代调用.save()
。跟踪保存文档时可能产生的错误,如果发生任何错误,则会中断迭代(您也可以选择继续)。
像这样的东西——
User.find({}, (err, users) => {
if (err) {
res.send(err);
}
let errorWhileSaving = null;
for (let user of users) {
if (errorWhileSaving) {
res.send(ererrorWhileSaving);
break;
}
user.name = req.body.name;
user.salary = req.body.salary;
user.save(function(err) {
errorWhileSaving = err;
});
}
res.json({ message: 'All User info updated' });
});
我从不推荐这种方法,因为我们使用这种方法会失去事务的原子性。保存任何用户时的任何失败都会导致数据库的部分更新,这确实是有害的。
此外,它还向数据库服务器发出多个查询,这肯定会影响事务的性能。
我所说的事务是指在数据库上运行的任何一组查询(简单或复杂)。
2. 推荐
不要先使用.find()
然后迭代文档,然后通过发出多个.save()
调用来保存它们,而是使用.update()
方法。
有点像这样——
User.update(
{},
{
$set: {
name: req.body.name,
salary: req.body.salary
}
},
{
multi: true
},
function (err, results) {
if (err) {
res.send(err);
}
res.json({ message: 'All User info updated' });
}
);
解释
.update
方法期望 -
- 搜索条件 - 将用于查找要更新的文档的条件。 在这里,我们提供了
{}
这意味着我们要更新users
集合中的所有文档。 - 更新选项 - 这些选项是
mongodb
的更新运算符。 在这里,我们使用$set
在所有文档上设置两个字段。 - 表示查询行为的对象。在这里,我们使用了
{muti: true}
,它要求mongodb对与搜索条件匹配的多个文档运行此更新查询。 - 回调(可选)- 查询完成执行后将调用的函数,出现错误或结果。
使用这种方法的好处是 -
- 要么所有用户都会得到更新,要么没有人会更新。原子数
- 向数据库发出单个查询,从而提高查询性能。
您可以在mongodb文档中找到有关.update()
的更多信息。
改进点
我注意到,您仍在使用回调来处理异步任务。如果你还不熟悉承诺,那就去研究它们,而不是使用回调,优化你的代码以使用承诺。我见过优秀的应用程序开发人员努力推理包含在回调中的代码,所以要明智地开始使用 Promise 以获得更好的未来。
这是一篇从承诺开始的好文章。