2017-05-04 8 views
0

私はかなりmongoose/expressを新しくしています。私が苦労しているのは、新しいデータを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は、コード作成サービスではなく、Q&Aサイトです。効果的な質問を書く方法については、こちらをご覧ください(https://stackoverflow.com/help/how-to-ask)。 – Teocci

答えて

0

BusinessLocationContactは異なるコレクションです。

findByIdAndUpdateは、1つのコレクションのみを更新します(具体的にはBusiness)。他のコレクションを更新するには、それらのコレクションに対して操作を実行する必要があります。

「既存の」場所と連絡先を更新する場合は、そのIDも指定する必要があります。また、場所と連絡先の「配列」があるので、あなたの名前にさらに[]が必要です。私の(とothers)の経験から

<% 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 --> 
<% }) %> 

、私は一度に複数のドキュメントを更新することが可能であるとは思いません。つまり、ルートハンドラーでは、指定された配列の各項目を繰り返し処理し、それらを1つずつ更新する必要があります。あなたが非同期的なマングース操作を行うために同期forEachを使用してはならないので、他の投稿の答えは、まったく正しいIMOではありません。予期しない動作につながるからです。

ビジネスの更新、既存の場所の更新、および既存の連絡先の更新の3つの主要なタスクがあります。

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を使用して保存し、コードの最後にリダイレクトすることができました。連絡先と場所については、forEachで連絡先と場所を個別にfindByIdAndUpdateを使用しなければなりませんでした。いくつかの行を追加しますが、それらを最もよくリファクタリングする方法を理解するつもりです。私が前に言ったように、これはかなり新しいものであり、まだその工芸品を学んでいます。しかし、私はあなたの助けを借りてそれを働かせることができました! –

関連する問題