2017-05-04 94 views
0

我对猫鼬/快车相当陌生。我正在努力尝试更新来自HTML表单的新数据并将其保存到具有引用的数据库。我有一个带位置模型位置参考的商业模型。这是代码。更新带有多个参考数据库问题的数据库

edit.ejs

<div class="container"> 
    <div class="form-container"> 
     <form action="/<%= bus._id %>?_method=PUT" method="POST"> 
      <!-- business info --> 
      <h3>Business Information</h3> 
      <input class="form-input" type="input" name="bus[logo]" value="<%= bus.logo %>"> 
      <input class="form-input" type="input" name="bus[name]" value="<%= bus.name %>"> 
      <% bus.location.forEach(function(location) { %> 
      <input class="form-input" type="input" name="bus.location[street]" value="<%= location.street %>"> 
      <input class="form-input" type="input" name="bus.location[city]" value="<%= location.city %>"> 
      <div class="state-input"> 
       <select class="form-inline" name="bus.location[state]"> 
        <option value="" disabled selected><%= location.state %></option> 
        <option value="AL">Alabama</option> 
        ... 
        <option value="WY">Wyoming</option> 
       </select> 
      </div><!--State-input --> 
      <input class="form-inline" type="input" name="bus.location[zipcode]" value="<%= location.zipcode %>"> 
      <% }) %> 
      <!--Contact info--> 
      <h4>Contact Information</h4> 
      <% bus.contact.forEach(function(contact) { %> 
      <input class="form-input" type="url" name="bus[url]" value="<%= bus.url %>"> 
      <input class="form-input" type="email" name="bus.contact[email]" value="<%= contact.email %>"> 
      <input class="form-input" type="tel" name="bus.contact[phone]" value="<%= contact.phone %>"> 
      <input class="form-input" type="input" name="bus.contact[twitter]" value= "<%= contact.twitter %>"> 
      <input class="form-input" type="input" name="bus.contact[facebook]" value="<%= contact.facebook %>"> 
      <input class="form-input" type="input" name="bus.contact[instagram]" value="<%= contact.instagram %>"> 
      <% }) %> 

index.js - 编辑路线

//(edit.ejs) Edit Route 
app.get('/:id/edit', function(req, res) { 
    Business.findById(req.params.id) 
    .populate('location') 
    .populate('contact') 
    .populate('images') 
    .exec(function(err, bus) { 
     if(err) { 
      console.log(err); 
     } else { 
      res.render('edit', {bus:bus}); 
     } 
    }); 
}); 
app.put('/:id', function(req, res) { 
    Business.findByIdAndUpdate(req.params.id, req.body.bus, function(err, bus) { 
     if(err) { 
      console.log(err); 
      res.redirect('/' + req.params.id + '/edit'); 
     } else { 
      res.redirect('/' + req.params.id); 
     } 
    }); 
}); 

业务(公交车)更新很好,但bus.location不更新。 商业模式

//----------------------------------------------------------------------------\\ 
var mongoose = require('mongoose'); 
//----------------------------------------------------------------------------\\ 
var busSchema = new mongoose.Schema({ 
    name: String, 
    type: String, 
    logo: String, 
    desc: String, 
    subs: Number, 
    video: String, 
    url: String, 
    firstRun: Boolean, 
    location:[ 
     { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: 'Location' 
     } 
    ], 
    contact:[ 
     { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: 'Contact' 
     } 
    ], 
    images:[ 
     { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: 'Image' 
     } 
    ], 
    comments:[ 
     { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: 'Comment' 
     } 
    ], 
    created: { 
     type: Date, default: Date.now 
    } 
}); 
//----------------------------------------------------------------------------\\ 
module.exports = mongoose.model('Business', busSchema); 

选址模型

//----------------------------------------------------------------------------\\ 
var mongoose = require('mongoose'); 
//----------------------------------------------------------------------------\\ 
var locSchema = new mongoose.Schema(
    { 
     street: String, 
     city: String, 
     state: String, 
     zipcode: Number 
    } 
); 
//----------------------------------------------------------------------------\\ 
module.exports = mongoose.model('Location', locSchema); 
+0

欢迎来到Stack Overflow。什么是错误?数据如何流动?你能解释你的代码吗?在提问之前,始终要具体并尽力而为,并且不要将Stack Overflow当作教程的存储库。堆栈溢出是一个问答网站,而不是代码写入服务。请[见这里](https://stackoverflow.com/help/how-to-ask)学习如何编写有效的问题。 – Teocci

回答

0

BusinessLocationContact是不同的集合。

findByIdAndUpdate只更新一个集合,其中特别是你的Business。为了更新其他集合,您需要对这些集合执行操作。

如果您尝试更新“现有”位置和联系人,则还需要提供其ID。此外,你有一个“阵列”的位置和联系人,所以你需要额外的[]你的名字。

<% bus.location.forEach(function(location, i) { %> 
    <input type="hidden" name="location[<?= i ?>][id]" value="<%= location.id %>"> 
    <input class="form-input" type="input" name="location[<?= i ?>][street]" value="<%= location.street %>"> 
    <!-- etc --> 
<% }) %> 

<% bus.contact.forEach(function(contact, i) { %> 
    <input type="hidden" name="contact[<?= i ?>][id]" value="<%= contact.id %>"> 
    <input class="form-input" type="email" name="contact[<?= i ?>][email]" value="<%= contact.email %>"> 
    <!-- etc --> 
<% }) %> 

从我(和others)的经验,我不认为这是可能在一次更新多个文件。这意味着,在您的路由处理程序中,您将需要遍历数组中的每个项目,并逐个更新它们。在其他帖子中的答案虽然不是很正确的IMO,因为你不应该使用同步forEach做异步猫鼬操作,因为它会导致意外的行为。

您有三项主要任务:更新业务,更新其现有位置并更新其现有联系人。

我喜欢用async.js来执行多个异步操作。在你的具体情况下,我将使用async.series来完成每个任务,async.eachSeries对阵列的每个元素执行一个操作。

警告这是未经测试,但它会是这个样子:

app.put('/:id', function(req, res) { 

    console.log(req.body.bus); 
    console.log(req.body.location); // should be an array of objects 
    console.log(req.body.contact); // should be an array of objects 

    // perform each task one by one 
    async.series([ 
     function updateBusiness (done) { 
      // you need to always call the callback i.e. done to indicate the task is "done" 
      // - if you pass an error as an argument, it means the task failed and stop everything 
      // - otherwise, move onto the next task 

      /*Business.findByIdAndUpdate(req.params.id, req.body.bus, function (err) { 
       if (err) { 
        return done(err); // task failed and stop everything 
       } 
       done(); // task went well and proceed to the next task 
      });*/ 

      // simplified 
      Business.findByIdAndUpdate(req.params.id, req.body.bus, done); 
     }, 
     function updateLocations (done) { 
      // find and update each location 
      async.eachSeries(req.body.location || [], function (location, done2) { 
       Location.findByIdAndUpdate(location.id, location, done2); 
      }, done); 
     }, 
     function updateContacts (done) { 
      // find and update each contact 
      async.eachSeries(req.body.contact || [], function (contact, done2) { 
       Contact.findByIdAndUpdate(contact.id, contact, done2); 
      }, done); 
     } 
    ], function allDone (err) { 
     // a task failed somewhere 
     if (err) { 
      console.log(err); 
      res.redirect('/' + req.params.id + '/edit'); 
     // all tasks were completed 
     } else { 
      res.redirect('/' + req.params.id); 
     } 
    }); 
}); 

如果有错误,看看控制台日志。

+0

当您建议为联系人和位置添加其他[] ID时,我能够计算出我的代码结构出了什么问题。我不熟悉async.js工具,但打算查看。谢谢! –

+0

好奇:随着你的改变,它真的使用'Business.findByIdAndUpdate'保存吗?还是你必须做更多? – Mikey

+0

是的,我可以使用Business.findByIdAndUpdate进行保存,然后在代码结束时重定向。至于联系方式和位置,我必须使用findByIdAndUpdate单独与forEach进行联系和定位。占用更多的线路,但打算想出如何最好地重构它们。正如我之前所说的,对此并不陌生,仍然在学习这种工艺。但是,我能够得到它的帮助! –