Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
573 views
in Technique[技术] by (71.8m points)

node.js - Mongoose - Form to save model with embedded documents

Having trouble saving an embedded array to a Mongoose model.

Please see Edit at bottom.

I have a form to create BlogPost in Express using Mongoose to store data in mongo. I can create and view new blogposts however I just added an embedded document schema Feed into the BlogPost model and I can't get Feed arrays to save from the form into the model

code:

BlogPosts.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_database');

var Schema = mongoose.Schema
  , ObjectId = Schema.ObjectId;

var Feeds = new Schema({
    name      : { type: String }
  , key       : { type: String }
});

var BlogPost = new Schema({
    author    : ObjectId
  , title     : { type: String, required: true, index: { unique: true } }
  , date      : { type: Date, required: true, default: Date.now }
  , feeds     : [Feeds]
});

mongoose.model('BlogPost', BlogPost);

web.js

...
app.get('/blogpost/new', function(req, res) {
    res.render('blogposts/blogpost_new.jade', { locals: {
        title: 'New BlogPost'
    }
    });
});

app.post('/blogpost/new', function(req, res){
    var b = new BlogPost(req.body.b)
    b.save(function() {
      b.feeds.push();
      res.redirect('/blogposts');
    });
});
...
var BlogPost = mongoose.model('BlogPost', BlogPost);

Jade form

form( method="post")
  div
    div
      span Title :
      input(type="text", name="b[title]", id="editBlogPostTitle")
    div 
      span Feeds :
      ul 
        li 
          span name
          textarea( name="f[name]", rows=20, id="editBlogPostBodyName")
        li
          span key
          textarea( name="f[key]", rows=20, id="editBlogPostBodyKey")
    div#editBlogPostSubmit
      input(type="submit", value="Send")

If I fill out this form, the model posts and saves but the feeds data isn't there ("feeds" : [ ]).

How should I properly submit the feeds data to save to the array?

Edit

So I have managed to set up a form to save a Feed object with name and key within a BlogPost doing the following. However, this still needs to be improved to allow for multiple Feeds to be saved at the time of creating a single BlogPost. With my current solution I can only save one Feed properly. Thoughts?

blogposts.js (just change Feeds to Feed

var Feed = new Schema({
...

web.js (just moved the push)

app.post('/blogpost/new', function(req, res){
    var b = new BlogPost(req.body.b)
    b.feeds.push(req.body.feed);
    b.save(function() {
      res.redirect('/blogposts');
});

});

form (just change feed names)

    li
        span name
        textarea( name="feed[name]", rows=20, id="editBlogPostBodyKey")
    li
        span key
        textarea( name="feed[key]", rows=20, id="editBlogPostBodyKey")

This saves properly, I just can't create multiple feeds within a blogpost at the time of saving. Any help greatly appreciated. thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For the routes:

You do not need to do b.feeds.push(); on the post side. I have a push on the get side when creating a new object, but only because I expect there to be at least 1 nested model. Then again, seeing as how you have a list you may want to add the b.feeds.push(); on the get side as well.

For the view, you need to keep the model intact.

Assuming b is blogpost and it is your parent to the f list, then you'd want:

span Feeds :
  - var i = 0;
  ul
  - each feed in blogPost.feeds
    li 
      span name
      textarea( name="blogPost[feeds][i][name]", rows=20, id="editBlogPostBodyName")=feed.name
    li
      span key
      textarea( name="blogPost[feeds][i][key]", rows=20, id="editBlogPostBodyKey")=feed.key
    - i++

routes.js (or routes/blogPosts.js):

app.get('/blogpost/new', function(req, res) {
    post = new BlogPost();
    post.feeds.push(new Feed());
    res.render('blogposts/blogpost_new.jade', { locals: {
        title: 'New BlogPost',
        blogPost: post
    }
    });
});

edit i changed b to blogPost and f to feed in the view. also added the "new" logic in the routes definition.

On a side note, keep in mind that any routes will not be editable in this case. It should, in theory, drop and save any new feeds in the even of editing them (if you were to have an update action). If you want them to be independent entities that can be edited, then you need to provide them ids and have add a means of getting them by id. That approach is outlined on mongoosejs.com i believe.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...