我正在尝试替换url中的字符串。这是它的图片
在此图像中,我想将 lssplalpha 替换为pics数组中的 lssplprod 。为此,我创建了一个api。这是代码
apiRoutes.get('/SchoolListing_lssplalpha_Replace',function(req, res) { schoolListModel.find({},function(err,check){
if(err){
return console.log(err);
}
else{
for(var i=0;i<check.length;){
var f=0;
for(var j=0;j<check[i].pics.length;j++){
f++;
var newTitle = check[i].pics[j].replace("lssplalpha","lsslprod");
check[i].pics[j] = newTitle;
console.log("after change",check[i].pics[j]);
check[i].save(function (err) {
if(err) {
console.error('ERROR!');
}
});
}
if(j==check[i].pics.length&&j==f){
i++;
}
}
console.log("i value",i);
console.log("check length",check.length);
if(i==check.length){
return res.json({status:true,message:"Updated Schools"}); }
}
});
});
我得到了成功的回应。当我去检查数据库时,db中没有任何变化。要知道我写日志的原因。当我看到日志时,它正在正确替换。但是我不明白为什么这些没有反映在数据库中?这是登录控制台的图像
请帮助我解决这个问题
答案 0 :(得分:1)
这里的问题是,您正在运行一个for循环(同步),在该循环中您正在调用model.save()
操作,该操作是异步的,并且循环不断进行迭代,但是异步调用的结果稍后出现。将数据库项保存在数组中的过程需要一些时间,Node.js知道这一点,因此它开始更新,然后继续尝试更新数组中的下一项。一旦写操作完成,便会运行一个回调函数,但是到那时循环已完成,并且无法知道哪些项目以什么顺序完成。
您可以使用Bulk Write API来更新模型。这使您可以通过一个命令将多个写入操作发送到MongoDB服务器。这比发送多个独立操作(例如,如果您使用create())要快,因为使用 bulkWrite()
时,只有一次往返MongoDB的行程。
以下示例显示了如何使用bulkWrite。
使用异步/等待:
apiRoutes.get('/SchoolListing_lssplalpha_Replace', async (req, res) => {
try {
let ops = [];
const docs = await schoolListModel.find({}).lean().exec();
docs.forEach(doc => {
const pics = doc.pics.map(pic => pic.replace("lssplalpha", "lsslprod"));
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { pics }
}
}
});
});
const result = await schoolListModel.bulkWrite(ops);
console.log('Bulk update complete.', result);
res.status(200).json({
status: true,
message: "Updated Schools"
});
} catch (err) {
res.status(400).send({
status: false,
message: err
});
}
});
使用Promise API:
const bulkUpdate = (Model, query) => (
new Promise((resolve, reject) => {
let ops = [];
Model.find(query).lean().exec((err, docs) => {
if (err) return reject(err);
docs.forEach(doc => {
const pics = doc.pics.map(pic => (
pic.replace("lssplalpha", "lsslprod")
));
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { pics }
}
}
});
if (ops.length === 500) {
Model.bulkWrite(ops).then((err, result) => {
if (err) return reject(err);
ops = [];
resolve(result);
});
}
});
if (ops.length > 0) {
Model.bulkWrite(ops).then((err, result) => {
if (err) return reject(err);
resolve(result);
});
}
});
})
);
apiRoutes.get('/SchoolListing_lssplalpha_Replace', (req, res) => {
bulkUpdate(schoolListModel, {}).then(result => {
console.log('Bulk update complete.', result);
res.status(200).json({
status: true,
message: "Updated Schools"
});
}).catch(err => {
res.status(400).send({
status: false,
message: err
});
});
});
答案 1 :(得分:1)
您正在for循环中运行异步调用 model.save()(同步)
要使您的for循环同步,您可以使用f 或... of 循环,该循环可以异步工作,也不需要像在代码中一样添加多个检查。
尝试以下代码,它将起作用
library(tidyverse)
mydf <- data_frame(value=c(1:3,1:3),
total=rep(c(10,20),times=3),
cond=rep(c("x","y","z"),times=2),
group=rep(c("a","b"),each=3))
mydf %>% ggplot(aes(x="",y=value,fill=cond)) +
geom_bar(stat="identity",width=1) +
facet_wrap(~ group) +
coord_polar("y")