我正在设置种子数据,目标是只创建一条记录(如果它还不存在)。
我使用https://www.npmjs.com/package/mongoose-find-one-or-create插件只创建记录,如果它们不存在且无法正常工作。
我还调试了他们的代码并编写了我自己的测试。
我原本希望看到“发现”这个消息,但我得到一条名为'Xyz'的新记录
我感觉它可能是某种异步问题,但我是mongo的新手,所以不完全确定。
以下是我的所有测试代码,以及plugin中的代码。
帐户表的方案定义
'use strict';
var mongoose = require('mongoose');
var findOneOrCreate = require('mongoose-find-one-or-create');
var Schema = mongoose.Schema;
var AccountSchema = new Schema({
name: String,
type: String,
notes: String,
locationIds: String,
});
AccountSchema.plugin(findOneOrCreate);
module.exports = mongoose.model('Account', AccountSchema);
用于创建新行的种子文件
'use strict';
var Account = require('../../api/account/account.model');
Account.create({ name: 'Abc' }, function (err, small) {
});
Account.findOne({ name: 'Abc' }, function (err, row) {
console.log("Inside Find One");
if (row) {
console.log("Found: Yes");
console.log(row);
} else {
console.log("NOT FOUND");
Account.create({ name: 'Xyz' }, function (err, small) {
});
}
});
FindOneOrCreatePlugin代码
'use strict';
/**
* Mongoose Plugin: findOneOrCreate
* Copyright(c) 2014 Mohammad Khan <mohammad.khan@gmx.us>
* MIT Licensed
**/
function findOneOrCreatePlugin(schema) {
//console.log('findOneOrCreatePlugin: SETUP');
schema.statics.findOneOrCreate = function findOneOrCreate(condition, doc, callback) {
var self = this;
//console.log('CONDITION');
//console.log('----------------------------------------------------------------------------------------------------');
//console.log(condition);
//console.log('----------------------------------------------------------------------------------------------------');
self.findOne(condition, function(err, result ) {
//console.log('ERROR');
//console.log('----------------------------------------------------------------------------------------------------');
//console.log(err);
//console.log('----------------------------------------------------------------------------------------------------');
//console.log('RESULT');
//console.log('----------------------------------------------------------------------------------------------------');
//console.log(result);
//console.log('----------------------------------------------------------------------------------------------------');
if (result) {
//console.log('----------------------------------------------------------------------------------------------------');
//console.log('YEEEEEEEEEEEEEEY an UPDATE');
//console.log('----------------------------------------------------------------------------------------------------');
callback(err, result);
} else {
//console.log('CREATE');
//console.log('----------------------------------------------------------------------------------------------------');
//console.log(doc);
//console.log('----------------------------------------------------------------------------------------------------');
self.create(doc, function(err, result) {
callback(err, result);
});
}
});
};
}
module.exports = findOneOrCreatePlugin;
在Mongo Shell中查询
Web服务器中的控制台输出
**这是我试图处理的用例**
注意:这是最终用户使用
生成的一组文件的一部分我试图解决的USE案例是,如果用户意外地将同一帐户放入两次。
当用户意外地放入重复项时,此代码本质上意味着自我修复,它只是用于填充新应用程序的种子系统。
我打算在产品表上使用它,产品表有1000个产品。
根据@RobertMoskal的说法,我需要将调用放在回调函数中,但是我会有大量的嵌套回调函数,每个产品都有1个。
// Create account called 'Chicane'
Account.findOneOrCreate(
{ name: 'Chicane'},
{
name: 'Chicane',
type: 'Orderer',
},
function (err, account) {
console.log('Account.findOneOrCreate');
console.log(account);
}
);
// Create account called 'Campos'
Account.findOneOrCreate(
{ name: 'Campos'},
{
name: 'Campos',
type: 'Supplier',
},
function (err, account) {
console.log('Account.findOneOrCreate');
console.log(account);
}
);
// Create account called 'Chicane', this has already been created so it should NOT be created again, but it is
Account.findOneOrCreate(
{ name: 'Chicane'},
{
name: 'Chicane',
type: 'Orderer',
},
function (err, account) {
console.log('Account.findOneOrCreate');
console.log(account);
}
);
答案 0 :(得分:1)
经典节点错误。您必须在create函数的回调中调用findOne函数,否则将在create函数完成之前调用它。所以像这样:
Account.create({ name: 'Abc' }, function (err, small) {
if(err)...;
Account.findOne({ name: 'Abc' }, function (err, row) {...
});
});
使用findOneOrCreate插件天真地加载数千个项目会导致回调地狱。但是您可以看到过程的重复性,您可以使用async库之类的东西来确保代码按顺序运行:
async.series([
function(cb){ Account.findOneOrCreate({...})},
function(cb){ { Account.findOneOrCreate({...}, cb)}
]);