MongoDB的 - 猫鼬 - 类型错误:拯救不是一个函数(MongoDB - Mongoose -

2019-11-05 04:41发布

我试图先用.findById获取文档,然后更新用新值在该文件中的字段进行更新到MongoDB的文件(使用猫鼬)。 我还是有点新本,所以我用了一个教程,弄清楚如何得到它的工作,然后我一直在更新我的代码为我的需求。 下面是本教程: MEAN应用教程与角4 。 原代码中定义了一个架构,但我的要求是一个通用的MongoDB的接口,将简单地采取一切有效载荷发送给它,并一起MongoDB的发送。 原来的教程有这样的事情:

exports.updateTodo = async function(todo){
    var id = todo.id

    try{
        //Find the old Todo Object by the Id

        var oldTodo = await ToDo.findById(id);
    }catch(e){
        throw Error("Error occured while Finding the Todo")
    }

    // If no old Todo Object exists return false
    if(!oldTodo){
        return false;
    }

    console.log(oldTodo)

    //Edit the Todo Object
    oldTodo.title = todo.title
    oldTodo.description = todo.description
    oldTodo.status = todo.status


    console.log(oldTodo)

    try{
        var savedTodo = await oldTodo.save()
        return savedTodo;
    }catch(e){
        throw Error("And Error occured while updating the Todo");
    }
}

然而,因为我不想要一个模式,并希望通过允许任何东西,我不想静态值分配给像,标题,描述,状态等特定字段名所以,我想出了这一点:

exports.updateData = async function(update){
    var id = update.id

    // Check the existence of the query parameters, If they don't exist then assign a default value
    var dbName = update.dbName ? update.dbName : 'test'
    var collection = update.collection ? update.collection : 'testing'; 

    const Test = mongoose.model(dbName, TestSchema, collection);

    try{
        //Find the existing Test object by the Id
        var existingData = await Test.findById(id);
    }catch(e){
        throw Error("Error occurred while finding the Test document - " + e)
    }

    // If no existing Test object exists return false
    if(!existingData){
        return false;
    }

    console.log("Existing document is " + existingData)

    //Edit the Test object
    existingData = JSON.parse(JSON.stringify(update))

    //This was another way to overwrite existing field values, but
    //performs a "shallow copy" so it's not desireable
    //existingData = Object.assign({}, existingData, update)

    //existingData.title = update.title
    //existingData.description = update.description
    //existingData.status = update.status

    console.log("New data is " + existingData)

    try{
        var savedOutput = await existingData.save()
        return savedOutput;
    }catch(e){
        throw Error("An error occurred while updating the Test document - " + e);
    }
}

我原来的问题,这是我有很多获得新的值来覆盖旧的问题。 现在,一个已经解决了,我得到的错误“类型错误:existingData.save不是一个函数”。 我想到的是数据类型改变什么的,现在它是不被接受。 当我取消那名老教程代码的静态值,它的工作原理。 这是由我的控制台记录,进一步支持了之前和之后我加入了对象,因为第一个打印的实际数据,第二个打印[对象的对象。 不过,我似乎无法找出它的预期。 任何帮助将不胜感激。

编辑:我想通了。 显然猫鼬有,如果你做任何事情,通过使用像JSON.stringify东西疯狂的底层数据,得到改变“模型”的它自己的数据类型。 我用Object.prototype.constructor找出实际的对象类型,如下所示:

console.log("THIS IS BEFORE: " + existingData.constructor);
existingData = JSON.parse(JSON.stringify(update));
console.log("THIS IS AFTER: " + existingData.constructor);

而我得到这个:

THIS IS BEFORE: function model(doc, fields, skipId) {
  model.hooks.execPreSync('createModel', doc);
  if (!(this instanceof model)) {
    return new model(doc, fields, skipId);
  }
  Model.call(this, doc, fields, skipId);
}
THIS IS AFTER: function Object() { [native code] }

这表明我究竟是怎么回事。 我加入这个解决它:

existingData = new Test(JSON.parse(JSON.stringify(update)));

与此相关的,我也许应该只使用本地MongoDB的司机在这一点上,但它的工作,所以我只是把它在我的待办事项清单上了。

Answer 1:

现在,您已经找到了解决办法,但我会建议使用MongoDB的驱动程序这将使你的代码看起来沿此线的东西,也会使原始问题消失:

// MongoDB Settings
const MongoClient = require(`mongodb`).MongoClient;
const mongodb_uri = `mongodb+srv://${REPLACE_mongodb_username}:${REPLACE_mongodb_password}@url-here.gcp.mongodb.net/test`;
const db_name = `test`;
let db; // allows us to reuse the database connection once it is opened

// Open MongoDB Connection
const open_database_connection = async () => {
  try {
    client = await MongoClient.connect(mongodb_uri);
  } catch (err) { throw new Error(err); }
  db = client.db(db_name);
};


exports.updateData = async update => {

  // open database connection if it isn't already open
  try {
    if (!db) await open_database_connection();
  } catch (err) { throw new Error(err); }


  // update document
  let savedOutput;
  try {
    savedOutput = await db.collection(`testing`).updateOne( // .save() is being depreciated
      { // filter
        _id: update.id // the '_id' might need to be 'id' depending on how you have set your collection up, usually it is '_id'
      },
      $set: { // I've assumed that you are overwriting the fields you are updating hence the '$set' operator
        update // update here - this is assuming that the update object only contains fields that should be updated
      }

      // If you want to add a new document if the id isn't  found add the below line
      // ,{ upsert: true }

    );
  } catch (err) { throw new Error(`An error occurred while updating the Test document - ${err}`); }


  if (savedOutput.matchedCount !== 1) return false; // if you add in '{ upsert: true }' above, then remove this line as it will create a new document

  return savedOutput;
}

收集testing将需要此代码之前要创建但是这仅仅是一次性的事情,是很容易-如果你正在使用MongoDB的阿特拉斯那么你可以使用MongoDB的北斗/去您的在线管理员创建集合没有一个单一的代码行...

至于我可以看到,如果您需要复制的update对象。 以上降低为2至一个调用数据库,并允许您在应用程序中,这将有助于加快速度重用数据库连接,可能其他地方。 也不要在代码中直接存储您的MongoDB的凭据。



文章来源: MongoDB - Mongoose - TypeError: save is not a function