2015-11-23 68 views
0

這是我的歌曲模式。 忽略import語句使用貓鼬保存引用對象的問題

var SongSchema = new mongoose.Schema({ 
    name: String, 
    genre: String, 
    artist: String, 
    album: String, 
    year: Number, 
    composer: String, 
    lyrics: String, 
    duration: Number // [seconds] 
}); 

var Song = module.exports = mongoose.model('Song', SongSchema); 

這是我的播放列表模式

var PlaylistSchema = new mongoose.Schema({ 
    name: String, 
    genre: String, 
    songs: [{ 
     details: { 
      type: mongoose.Schema.Types.ObjectId, 
      ref: 'Song' 
     }, 
     upvote_count: Number, 
     state: String, 
     type: String 
    }] 
}); 

var Playlist = mongoose.model("Playlist", PlaylistSchema); 

錯誤代碼:使用上面的代碼我收到以下錯誤保存該播放列表

console.log("object:", song.details); 
var newSong = new Song(song.details); 
newSong.save(); 
console.log("song:", newSong); 
newPlaylist.songs.push({ 
    details: newSong._id, 
    upvote_count: song.upvote_count || 0, 
    state: song.state || SongState.QUEUED, 
    type: song.type || SongType.NOT_FROZEN 
}); 

object: { name: 'String', 
genre: 'String', 
artist: 'String', 
album: 'String', 
year: 2010, 
composer: 'String', 
lyrics: 'String' } 
song: strictMode=true, selected=undefined, shardval=undefined, saveError=undefined, validationError=undefined, adhocPaths=undefined, removing=undefined, inserting=undefined, version=undefined, , _id=undefined, populate=undefined, populated=undefined, wasPopulated=false, scope=undefined, _id=default, duration=modify, lyrics=modify, composer=modify, year=modify, album=modify, artist=modify, genre=modify, name=modify, , _id=true, , duration=true, lyrics=true, composer=true, year=true, album=true, artist=true, genre=true, name=true, , stateNames=[require, modify, init, default, ignore], ownerDocument=undefined, fullPath=undefined, domain=null, , _maxListeners=0, isNew=true, errors=undefined, _bsontype=ObjectID, id=VSriÆùá÷%ß8, duration=42, lyrics=, composer=, year=2015, album=, artist=, genre=, name=, $__original_save=function() { 
    var self = this 
    , hookArgs // arguments eventually passed to the hook - are mutable 
    , lastArg = arguments[arguments.length-1] 
    , pres = this._pres[name] 
    , posts = this._posts[name] 
    , _total = pres.length 
    , _current = -1 
    , _asyncsLeft = proto[name].numAsyncPres 
    , _asyncsDone = function(err) { 
     if (err) { 
      return handleError(err); 
     } 
     --_asyncsLeft || _done.apply(self, hookArgs); 
     } 
    , handleError = function(err) { 
     if ('function' == typeof lastArg) 
      return lastArg(err); 
     if (errorCb) return errorCb.call(self, err); 
     throw err; 
     } 
    , _next = function() { 
     if (arguments[0] instanceof Error) { 
      return handleError(arguments[0]); 
     } 
     var _args = Array.prototype.slice.call(arguments) 
      , currPre 
      , preArgs; 
     if (_args.length && !(arguments[0] == null && typeof lastArg === 'function')) 
      hookArgs = _args; 
     if (++_current < _total) { 
      currPre = pres[_current] 
      if (currPre.isAsync && currPre.length < 2) 
      throw new Error("Your pre must have next and done arguments -- e.g., function (next, done, ...)"); 
      if (currPre.length < 1) 
      throw new Error("Your pre must have a next argument -- e.g., function (next, ...)"); 
      preArgs = (currPre.isAsync 
         ? [once(_next), once(_asyncsDone)] 
         : [once(_next)]).concat(hookArgs); 
      return currPre.apply(self, preArgs); 
     } else if (!_asyncsLeft) { 
      return _done.apply(self, hookArgs); 
     } 
     } 
    , _done = function() { 
     var args_ = Array.prototype.slice.call(arguments) 
      , ret, total_, current_, next_, done_, postArgs; 

     if (_current === _total) { 

      next_ = function() { 
      if (arguments[0] instanceof Error) { 
       return handleError(arguments[0]); 
      } 
      var args_ = Array.prototype.slice.call(arguments, 1) 
       , currPost 
       , postArgs; 
      if (args_.length) hookArgs = args_; 
      if (++current_ < total_) { 
       currPost = posts[current_] 
       if (currPost.length < 1) 
       throw new Error("Your post must have a next argument -- e.g., function (next, ...)"); 
       postArgs = [once(next_)].concat(hookArgs); 
       return currPost.apply(self, postArgs); 
      } else if (typeof lastArg === 'function'){ 
       // All post handlers are done, call original callback function 
       return lastArg.apply(self, arguments); 
      } 
      }; 

      // We are assuming that if the last argument provided to the wrapped function is a function, it was expecting 
      // a callback. We trap that callback and wait to call it until all post handlers have finished. 
      if(typeof lastArg === 'function'){ 
      args_[args_.length - 1] = once(next_); 
      } 

      total_ = posts.length; 
      current_ = -1; 
      ret = fn.apply(self, args_); // Execute wrapped function, post handlers come afterward 

      if (total_ && typeof lastArg !== 'function') return next_(); // no callback provided, execute next_() manually 
      return ret; 
     } 
     }; 

    return _next.apply(this, arguments); 
}, save=function wrappedPointCut() { 
    var args = [].slice.call(arguments); 
    var lastArg = args.pop(); 
    var fn; 

    return new Promise.ES6(function(resolve, reject) { 
    if (lastArg && typeof lastArg !== 'function') { 
     args.push(lastArg); 
    } else { 
     fn = lastArg; 
    } 
    args.push(function(error, result) { 
     if (error) { 
     self.$__handleReject(error); 
     fn && fn(error); 
     reject(error); 
     return; 
     } 

     fn && fn.apply(null, [null].concat(Array.prototype.slice.call(arguments, 1))); 
     resolve(result); 
    }); 

    self[newName].apply(self, args); 
    }); 
}, $__original_save=[function (next, options) { 
    // Nested docs have their own presave 
    if (this.ownerDocument) { 
    return next(); 
    } 

    var hasValidateBeforeSaveOption = options && 
    (typeof options === 'object') && 
    ('validateBeforeSave' in options); 

    var shouldValidate; 
    if (hasValidateBeforeSaveOption) { 
    shouldValidate = !!options.validateBeforeSave; 
    } else { 
    shouldValidate = this.schema.options.validateBeforeSave; 
    } 

    // Validate 
    if (shouldValidate) { 
    // HACK: use $__original_validate to avoid promises so bluebird doesn't 
    // complain 
    if (this.$__original_validate) { 
     this.$__original_validate({ __noPromise: true }, function(error) { 
     next(error); 
     }); 
    } else { 
     this.validate({ __noPromise: true }, function(error) { 
     next(error); 
     }); 
    } 
    } else { 
    next(); 
    } 
}, function (next, done) { 
    var Promise = PromiseProvider.get(), 
     subdocs = this.$__getAllSubdocs(); 

    if (!subdocs.length || this.$__preSavingFromParent) { 
    done(); 
    next(); 
    return; 
    } 

    new Promise.ES6(function(resolve, reject) { 
    async.each(subdocs, function(subdoc, cb) { 
     subdoc.$__preSavingFromParent = true; 
     subdoc.save(function(err) { 
     cb(err); 
     }); 
    }, function(error) { 
     for (var i = 0; i < subdocs.length; ++i) { 
     delete subdocs[i].$__preSavingFromParent; 
     } 
     if (error) { 
     reject(error); 
     return; 
     } 
     resolve(); 
    }); 
    }).then(function() { 
    next(); 
    done(); 
    }, done); 
}], $__original_save=[] 
CastError: Cast to string failed for value "[object Object]" at path "songs" 
at MongooseError.CastError (/media/D/codebin/grep/node_modules/mongoose/lib/error/cast.js:19:11) 
at SchemaString.cast (/media/D/codebin/grep/node_modules/mongoose/lib/schema/string.js:434:9) 
at Array.MongooseArray.mixin._cast (/media/D/codebin/grep/node_modules/mongoose/lib/types/array.js:124:32) 
at Array.MongooseArray.mixin._mapCast (/media/D/codebin/grep/node_modules/mongoose/lib/types/array.js:295:17) 
at Object.map (native) 
at Array.MongooseArray.mixin.push (/media/D/codebin/grep/node_modules/mongoose/lib/types/array.js:308:25) 
... 

如您所見,我保存的newSong具有函數的值。有人可以指出我哪裏錯了。

回答

0

您的PlaylistSchema不正確。仔細看看'歌曲'數組 - 你有一個type字段,所以貓鼬將模式解釋爲「歌曲是一串字符串」。將type字段重命名爲kind或設置custom typeKey,它應該工作。

+0

謝謝@vkarpvov,但我不明白播放列表的模式將如何影響歌曲的保存。我的猜測是返回的對象是一個承諾,但文檔說它應該是保存的對象。 – Tanmay