2017-05-04 81 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進行聯繫和定位。佔用更多的線路,但打算想出如何最好地重構它們。正如我之前所說的,對此並不陌生,仍然在學習這種工藝。但是,我能夠得到它的幫助! –