简体   繁体   中英

How to save data when you tried to reference the schema

I am trying to save information from a book that contains in its eschema auhtor and genre that I have it referenced in different files.

The problem is that when I make the reference in the main eschema. The book to have the reference of the author and the genre with the created book only keeps me the information of the book but does not make reference neither to the gender nor to the author

book.js

   const mongoose = require('mongoose');

const bookSchema = new mongoose.Schema({
  name: {
    type: String,
  },
  author: {
    type: mongoose.Schema.ObjectId,
    ref: 'Author', 
  },
  numberInStock: {
    type: Number,
    default: 0,
  },
  image: {
    type: String,
    default: '/path/to/default/image.png',
  },
  genre: {
    type: mongoose.Schema.ObjectId,
    ref: 'Genre',  
  },
});


module.exports = mongoose.model('Books', bookSchema);

author.js

const mongoose = require('mongoose');


const authorSchema = new mongoose.Schema({
  name: String,
  publicatons: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Book',
  }],
});


module.exports = mongoose.model('Author', authorSchema);

createBook.ejs

<div class="container h-100">
    <div class="row">
        <div class="col-lg-6 col-md-offset-3">
            <h1>Add a New Book</h1>
            <form action="/books/new/create" method="post">
                <div class="panel panel-default">
                    <div class="panel-body">
                        <div class="form-group">
                            <label for="book_name"> Book Name: </label>
                            <input type="text"  class="form-control" name="name">
                        </div>
                         <div class="form-group">
                            <label for="exampleFormControlSelect1">Author</label>
                            <select class="form-control"  name="<%= author._id %>">
                            <% author.forEach(function(authors){ %>
                            <option><%= authors._id %></option>
                            <% }); %>
                            </select>
                        </div>
                        <div class="form-group">
                            <label for="exampleFormControlSelect1">Genre</label>
                            <select class="form-control"  name="<%= genre._id %>">
                            <% genre.forEach(function(genres){ %>
                            <option><%= genres.name %></option>
                            <% }); %>
                            </select>
                        </div>
                        <div class="form-group">
                            <label for="numberInStock">Number in stock: </label>
                            <input type="number"  class="form-control" name="numberInStock">
                        </div>
                        <div class="form-group">
                            <label for="image">Image: </label>
                            <input type="text"  class="form-control" name="image">
                        </div>
                        <button type="submit" class="btn btn-success">Success</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

this is the part of the front where I try to send the data to the backent, but only manage to save, the name, image, quantity but not the referenced data.

controller.js

   const create = (req, res, next) => {
  if (!req.body) {
    return res.status(400).json({
      error: 'No data',
    });
  }
  const book = new Books(req.body);
  book.save((err, result) => {
    if (err) {
      return res.status(400).json({
        error: err.message,
      });
    }


    return res.status(201).json({
      message: 'Book created succesfully',
      result,

    });
  });
};

Routes controller

const express = require('express');

const router = express.Router();
const bookController = require('../controllers/book');
const booksave = require('../controllers/create');
const authorController = require('../controllers/author');
const genreController = require('../controllers/genre');

router.get('/books/home/:page', bookController.list);

router.get('/books/new', bookController.createTemplate);
router.post('/books/new/create', booksave.create);

router.get('/books/details/:id', bookController.bookDetail);

router.get('/books/new/create/genre', genreController.createGenreTemplate);
router.post('/books/new/genre', genreController.createGenre);

router.get('/books/new/create/author', authorController.createAuthorTemplate );
router.post('/books/new/author', authorController.createAuthor);




module.exports = router;

create new book render

controller.createTemplate = (req, res) => {
  Author.find({}, (err, allAuthors) => {
    if (err) {
      console.log(err);
    } else {
      Genre.find({}, (err, allGenres) => {
        if (err) {
          console.log(err)
        } else {
          res.render('new', { author: allAuthors, genre: allGenres });
        }
      })

    }
  });
};

technically what I hope to obtain is that when I save the information of the book this has a reference to its author and to the genre and automatically the author has a references to the books that are referenced with the same

Change the name attribute in <select class="form-control" name="<%= genre._id %>"> to name='author' same as in your bookSchema , and in <select class="form-control" name="<%= genre._id %>"> to name='genre' .
The problem is your sending a post request with the following body :

{ name: /*value*/ , <%= author._id%>: /*value*/, <%= genre._id%>: /*value*/, numberInStock: /*value*/, image: /*image*/ }

The constructor of your Book model recognizes name, numberInStock and image , but not <%=author_id%> and <%=genre._id%> .
Change this also:

author: {
    type: mongoose.Schema.ObjectId,
    ref: 'Author'
  },
genre: {
    type: mongoose.Schema.ObjectId,
    ref: 'Genre'
}

to

author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: ref: 'Author'
}
genre: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Genre'
}

You also need to pass genre._id instead of genres.name , and author._id as value attributes like this :



<form action="/books/new/create" method="post">
    <select name="author">
    <% author.forEach(function(authors){ %>
      <option value="<%= authors._id %>" ><%= authors.name %></option>
    <% }); %>
    </select>
    <select name="genre">
    <% genre.forEach(function(genres){ %>
      <option value="<%= genres._id %>" ><%= genres.name %></option>
    <% }); %>
    </select>
    <button type="submit">Success</button>
</form>


Of the values of the front I'm just getting

{name: 'Digital Fortress', numberInStock: '', image: ''}


const create = (req, res, next) => {
  if (!req.body) {
    return res.status(400).json({
      error: 'No data received',
    });
  }
  const book = new Books(req.body); 
  book.save((err, result) => {
    if (err) {
      return res.status(400).json({
        error: err.message,
      });
    }

    console.log(req.body);
    return res.status(201).json({
      message: 'Book created succesfully',
      result,

    });
  });
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM