Updating a record with mongoose

余生颓废 提交于 2019-12-02 17:55:58

问题


I'm learning MEAN stack applications and am working on a tv watchlist app. I built the api successfully without the seasons field in the model. Now I'd like to add this field so that a user can add seasons and episodes to the document to keep track of episodes they have watched. Through trial and error I found the query I'd use in the mongo shell to update a field in the episodes object but I can't create the right syntax to do this with mongoose inside my route. Can someone look in my tele.js routes at the router.put and tell me what's wrong.

Models (TVSeries.js)

var mongoose = require('mongoose')
var Schema = mongoose.Schema

var tvSchema = new Schema({
  title:String,
  poster:String,
  rated:String,
  program_time:Number,
  network:String,
  airs_on:[],
  streams_on:[],
  genre:[],
  seasons:[
            season_number:Number,
            episodes:[
                       {
                         episode_number:Number,
                         title:String,
                         watched:Boolean
                       }
                     ]
          ]
}, {collection: 'tvShows'});

module.exports = mongoose.model('tv', tvSchema);

Routes (tele.js)

var express = require('express');
var router = express.Router();
var TV = require('../models/TVSeries.js');

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Your Watchlist' });
});

router.get('/api/shows/:id/seasons', function(req, res){
    TV.findById(req.params.id, 'seasons', function(err, data){
        if(err){console.log(err)}
        else{res.json(data)};
    });
});

router.put('/api/shows/:id/seasons/:sid', function(req, res){
    var setField = {
        seasons:[
            {
                season_number:req.params.sid,
                episodes:[
                    req.body
                    ]
            }
        ]
    }

    TV.findOneAndUpdate({"_id":req.params.id}, setField, {upsert:true}, function(err, results){
       if(err){console.log(err)}
       else{
           console.log(setField);
           res.json(results)
       }
    })
})

module.exports = router;

Mongo Shell command

db.tvShows.update({"_id":ObjectId('######################')},{$set: {'seasons.1.episodes.1.title':'This is my title change'}})

回答1:


You can use &elementMatch to find the desire season in the array, and in the setField object you can use the positional $ operator which identify the element matched in the query.

The problem is that if it doesn't find any season that match the season_number, the document will not be updated. In this case you can set another update query to add this season in the seasons array.

router.put('/api/shows/:id/seasons/:sid', function(req, res){

  var query = {
    "_id": req.params.id,
    "seasons": { 
      $elemMatch: { 
        "season_number": req.params.sid 
      } 
    }
  }

  var setField = {
    $addToSet: {
      "seasons.$.episodes": req.body
    }
  }

  TV.findOneAndUpdate(query, setField, {upsert:true}, function(err, results){
    if (err && err.code == 16836) { // no document was matched
      var season = {
        "season_number": req.params.sid
        "episodes": [ req.body]
      }
      TV.findOneAndUpdate({"_id": req.params.id}, {$push: {"seasons": season}} , function(err, result) {
          console.log("Inserted document in array");
          res.json(result)
      }); 
    }
    else if (err){
       console.log(err);
       res.status(500).send('Something wrong!');
    }
    else {
       console.log(setField);
       res.json(results)
    }
  })
})

You can see here some mongodb array operators.

Hope it helps.



来源:https://stackoverflow.com/questions/40330916/updating-a-record-with-mongoose

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!