0

我正在设置种子数据,目的是仅在不存在的情况下创建记录。

我正在使用https://www.npmjs.com/package/mongoose-find-one-or-create插件仅在记录不存在且不起作用时才创建记录。

我还调试了他们的代码并编写了自己的测试,执行以下操作。

  • 创建记录 - 名称 = 'Abc'
  • 查找名称 = 'Abc' 的记录
  • 如果找到
  •     打印找到
  • 如果没有找到
  •     创建记录 - 名称 = 'Xyz'

我期待看到消息“找到”,但我得到了一条名为“Xyz”的新记录

我觉得这可能是某种异步问题,但我是 mongo 的新手,所以不完全确定。

这是我所有的测试代码,以及插件中的代码。

账户表的方案定义

'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 中的查询

Mongo Shell 输出

Web 服务器中的控制台输出

Web 服务器中的控制台输出

**这是我试图处理的用例**

注意:这是最终用户生成的一组文件的一部分

我试图解决的用例是如果用户不小心将同一个帐户放入了两次。

这段代码本质上是为了在用户意外放入重复代码时进行自我修复,它只是用于填充新应用程序的种子系统。

我确实计划在拥有 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);
    }
);
4

1 回答 1

2

经典的节点错误。必须在 create 函数的回调中调用 findOne 函数,否则会在 create 函数完成之前调用。所以是这样的:

Account.create({ name: 'Abc' }, function (err, small) {
    if(err)...;
    Account.findOne({ name: 'Abc' }, function (err, row) {...
    });
});

使用 findOneOrCreate 插件天真地加载数千个项目会导致回调地狱。但是您可以看到该过程的重复性,您可以使用诸如异步库之类的东西来确保您的代码按顺序运行:

async.series([
    function(cb){ Account.findOneOrCreate({...})},
    function(cb){ { Account.findOneOrCreate({...}, cb)}
]);
于 2015-09-07T22:40:21.137 回答