我尝试通过首先使用.findById获取文档,然后使用新值更新该文档中的字段来对MongoDB文档进行更新(使用猫鼬)。我对此还有些陌生,因此我使用了一个教程来弄清楚如何使其工作,然后根据需要更新了代码。这是本教程:MEAN App Tutorial with Angular 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);
}
}
我最初的问题是,我在获取新值以覆盖旧值时遇到很多问题。现在已经解决了,我得到了“ TypeError:existedData.save不是函数”的错误。我在考虑数据类型已更改或某些更改,现在不被接受。当我取消注释旧教程代码中的静态值时,它将起作用。在加入对象之前和之后,控制台日志进一步支持了这一点,因为第一个打印实际数据,第二个打印[对象对象]。但是,我似乎无法弄清楚它的期望。任何帮助将不胜感激。
编辑:我知道了。显然,Mongoose具有自己的“模型”数据类型,如果您通过使用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驱动程序,但是它可以正常工作,因此现在将其放入待办事项列表中。
答案 0 :(得分:0)
您现在已经找到了解决方案,但我建议使用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 Atlas,则可以使用MongoDB Compass /进入在线管理员创建没有一行代码的集合...
据我所知,您应该需要复制update
对象。上面的方法将数据库调用从2减少到1,并允许您在应用程序中的其他任何地方重用数据库连接,这将有助于加快处理速度。另外,请勿将您的MongoDB凭据直接存储在代码中。