javascript - Rethinkdb 和 Thinky 如何在具有 'hasMany' 关系的模型中的多个模型上 saveAll,其中父模型包含子模型数组

标签 javascript rethinkdb thinky

这个问题很难说清楚,但就是这样。最终,我在 RethinkDB 中有一组模型,它们以某种链模式相互关联。当我想要使用定义为“hasMany”关系的字段(使用 Thinky ORM)将一组 rethinkdb 模型放入其中以保存到数据库并创建与对象的关系时,我遇到了问题。

由于用段落来解释这非常困难且冗长,因此我创建了一个单独的测试用例来用代码说明我面临的问题。

var Reqlite = require('reqlite');
var assert = require('assert');

var thinky = require('thinky')({
    "host": "localhost",
    "port": 28016,
    "db": "test"
});

var server = new Reqlite({"driver-port": 28016});

var r = thinky.r;
var type = thinky.type;


// Models
var Account = thinky.createModel('accounts', {
    id: type.string(),
    username: type.string(),
});

var User = thinky.createModel('users', {
    id: type.string(),
    name: type.string(),
    accountId: type.string(),
    archetypeId: type.string(),
});

var Archetype = thinky.createModel('archetypes', {
    id: type.string(),
    name: type.string(),
});

var Node = thinky.createModel('nodes', {
    id: type.string(),
    skillId: type.string(),
    archetypeId: type.string(),
});

var Skill = thinky.createModel('skills', {
    id: type.string(),
    name: type.string(),
    desc: type.string(),
});


// Relationships
// Account <--> User
Account.hasMany(User, 'users', 'id', 'accountId');
User.belongsTo(Account, 'owner', 'accountId', 'id');

// User <--> Archetype
User.belongsTo(Archetype, 'archetype', 'archetypeId', 'id');

// Archetype <--> Node
Archetype.hasMany(Node, 'nodes', 'id', 'archetypeId');
Node.belongsTo(Archetype, 'archetype', 'archetypeId', 'id');

// Node <--> Skill
Node.belongsTo(Skill, 'skill', 'skillId', 'id');
Skill.hasMany(Node, 'nodes', 'id', 'skillId');


before(function(done) {

    var skillDebugging = Skill({
        id: '100',
        name: 'Debugging',
        desc: 'Increase knowledge of the inner working of things',
    });
    var skillBuilding = Skill({
        id: '110',
        name: 'Building',
        desc: 'Survive the Apocalypse with this',
    });

    var debuggerNode = Node({
        id: '200',
        skill: skillDebugging,
    });

    var builderNode = Node({
        id: '210',
        skill: skillBuilding,
    });

    var jackBuildNode = Node({
        id: '220',
        skill: skillBuilding,
    });
    var jackDebugNode = Node({
        id: '230',
        skill: skillDebugging,
    });

    var archetype1 = Archetype({
        id: '300',
        name: 'Debugger',
        nodes: [debuggerNode],
    });
    var archetype2 = Archetype({
        id: '310',
        name: 'Builder',
        nodes: [builderNode],
    });
    var archetype3 = Archetype({
        id: '320',
        name: 'Jack-O-Trades',
        nodes: [jackBuildNode, jackDebugNode],
    });

    archetype1.saveAll().then(function(result) {
        archetype2.saveAll().then(function(result1) {
            archetype3.saveAll().then(function(result2) {
                done();
            }).error(done).catch(done);
        }).error(done).catch(done);
    }).error(done).catch(done);
});

describe('New Test', function() {
    it('should return a list of archetypes with all joined nodes and skills', function(done) {
        Archetype.getJoin().then(function(archetypes) {
            // here we should expect to see the data saved and joined in each archetype as it was defined
            // above in the "before" block
            console.info('\nList of archetypes: ', JSON.stringify(archetypes));
            assert.ok(archetypes);

            archetypes.forEach(function(archetype) {
                assert.ok(archetype);
                assert.ok(archetype.nodes);
                archetype.nodes.forEach(function(node) {
                    assert.ok(node);
                    assert.ok(node.skill);
                });
            });
            done();
        }).error(done).catch(done);
    });

    it('should return a skill with a list of nodes joined', function(done) {
        Skill.get('100').getJoin().then(function(debugSkill) {
            console.info('\nDebug skill JSON: ', JSON.stringify(debugSkill));
            // if successful, we should see two nodes associated with this skill
            assert.ok(debugSkill);
            assert.ok(debugSkill.nodes);
            assert.ok(debugSkill.nodes.length > 1);
            done();
        }).error(done).catch(done);
    });
});

这是一个使用Reqlite模拟RethinkDB数据库的测试用例,thinky作为ORM,mocha作为测试套件来运行测试。在代码示例中,最后一个原型(prototype) id: '320' 和名称 Jack-O-Trades 是遇到问题的原型(prototype),另外两个原型(prototype)是在该原型(prototype)上构建的美好的。问题是,只有 jackBuildNode 被保存及其与 skill 模型的正确关联。 Jack-O-Trades 上的 nodes 数组中的第二个节点 jackDebugNode 已在数据库中保存并创建,但不保存关系该节点应具有 skillDebugging 技能模型。

任何人都可以看到我在代码和/或逻辑中可能出错的地方吗?我确实明白,有一些方法可以通过模块化保存并仅更新关系来解决这个问题,但是让单个 saveAll() 操作负责关联和创建此数据会更安全,因为单个操作更有可能在不损坏的情况下成功,因为将其分解为多个保存/更新调用可能会导致不完整的保存/更新。任何见解将不胜感激。

最佳答案

将此问题作为问题发布到 thinky github 后,我收到了作者的解决方案,该解决方案在问题中进行了描述。对于那些可能在这里寻找答案的人,问题摘要如下:

作者将不带参数使用的 thinky .saveAll() 方法描述为已弃用,并且应始终指定要保存的关系,以便递归 .saveAll() 方法适本地。查看thinky docs关于 .saveAll() 中传递的参数,并查看 neumino 发布的修改后的代码示例,了解如何稍微修改此代码示例以插入 saveAll 参数并保存正确的关系。

关于javascript - Rethinkdb 和 Thinky 如何在具有 'hasMany' 关系的模型中的多个模型上 saveAll,其中父模型包含子模型数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37983102/

相关文章:

javascript - 在javascript中转换数组

没有链接的 JavaScript blob 文件名

javascript - 如何使用 JavaScript 断点调试 WebStorm

javascript - 遍历数组并将项目与 html 元素匹配

rethinkdb - 如何找出 RethinkDB 表的大小?

javascript - 单独文件中的 thinky 模型 : how to handle cyclical/circular dependencies

javascript - RethinkDB - 将导入的 MySQL 时间戳字符串转换为时间对象

RethinkDB - 这是一个有效的乐观锁定实现吗

node.js - 如何匹配 Thinky ORM 中的字段?