2016-06-23 98 views
1

非常難以闡明的問題,但在這裏。最終,我在RethinkDB中有一組模型,它們以一種鏈式模式相互關聯。當我想用一個「hasMany」關係定義的字段,使用Thinky ORM,將一個rethinkdb模型數組放入以保存到數據庫並創建與對象的關係時,我遇到了一個問題。Rethinkdb和Thinky如何在具有'hasMany'關係的模型中的多個模型上保存所有模型,其中父模型包含子模型數組

由於這是非常艱難和漫長的段落來解釋,我已經創建了一個獨立的測試案例來說明,在代碼中,我面臨的問題。

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,和摩卡作爲測試套件運行測試的測試情況。在代碼示例中,最後一個原型id: '320'和名稱Jack-O-Trades是遇到問題的那個,其他兩個都沒問題。問題是,只有jackBuildNodeskill型號正確關聯才能保存。在nodes陣列上Jack-O-Trades的第二個節點,jackDebugNode被保存,並在數據庫中創建,但不保存該節點應與skillDebugging技能模型的關係。

任何人都可以看到我可能會在這裏的代碼和/或邏輯出錯嗎?我明白,我可以通過模塊化保存和更新後續關係來解決此問題,但單一操作後單個saveAll()操作負責關聯和創建此數據將更加安全如果將其分解爲多個保存/更新調用會導致未完成保存/更新的可能性,則更有可能成功而不會發生訛誤。任何有識之士將不勝感激。

回答

0

thinky github張貼這個問題作爲一個問題後,我收到了這是在描述的問題筆者的解決方案。對於那些可能尋找這裏的答案,問題的總結是這樣的:

沒有被描述爲傳遞的參數使用在Thinky中.saveAll()方法,通過筆者不贊成,應始終指定什麼關係你想要保存以便讓.saveAll()方法正確遞歸。查看關於在.saveAll()中傳遞的參數的thinky docs,並檢查neumino發佈的修改後的代碼示例,以查看此代碼示例是如何稍微修改以插入saveAll參數並獲取保存的適當關係的。

相關問題