2

我正在使用主干从一些平面数据中构建分层数据模型,并在尝试使用关系模型时遇到问题。以下代码的输出如下所示:

"D"
    "B"
        "C"
        "F"
    "G"
        "A"

其中每个字母对应于相关模型中的一个 id。当我将关联添加到 TreeNode 模型中以形成关系时,树停止迭代,我只得到第一组结果 (D > B > C) 而不是 (D > B > F) 或 (D > G > A ) 如我所愿。这是我添加关系时的输出:

{"label":"Fred","language":"en","id":"D","datatype":"number"}
    {"label":"is friends with","language":"en","id":"B","datatype":"text"}
        {"label":"Violet","language":"en","id":"C","datatype":"text"}

我是骨干关系的新手,不确定我是否正确执行此操作。这是示例代码(我尽可能将其配对,并用 HERE IS THE PROBLEM 指出问题区域)

提前致谢!!!

<!DOCTYPE html>
<html>
<head>
    <title>Relational Graph</title>
    <meta charset="utf-8" />
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.1/underscore-min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
    <script src="js/backbone.marionette.js"></script>
    <script src="js/backbone.relational.js"></script>
</head>
<body>

<div id="model"></div>

<script>

$(document).ready(function(){

    MainApp = new Backbone.Marionette.Application();
    MainApp.addRegions({treeRegion: "#model"});
    MainApp.addInitializer(function(options){
        var trunk = things.search({id: "D"}).first();
        var tree = new TreeNodeCollection(graphify(options.relationships, trunk));
        var treeView = new TreeRoot({collection: tree});
        this.treeRegion.show(treeView);
    });

    TreeNode = Backbone.RelationalModel.extend({
        initialize: function(){
            var nodes = this.get("nodes");
            if (nodes){
                this.nodes = new TreeNodeCollection(nodes);
                this.unset("nodes");
            }
        },
        render: function(){
            var that = this;
            TemplateManager.get(this.template, function(template){
                var html = $(template).tmpl();
                that.$el.html(html);
            });
            return this;
        }
        // !!! HERE IS THE PROBLEM - when I add this line, it stops looping through the tree :(
        //, relations: [{type: Backbone.HasOne, key: 'id', relatedModel: "Thing"}]
    });

    TreeNodeCollection = Backbone.Collection.extend({model: TreeNode});

    TreeView = Backbone.Marionette.CompositeView.extend({
        template: "#node-template",
        tagName: "ul",
        initialize: function(){
            this.collection = this.model.nodes;
        },
        appendHtml: function(collectionView, itemView){
            collectionView.$("li:first").append(itemView.el);
        }
    });

    TreeRoot = Backbone.Marionette.CollectionView.extend({itemView: TreeView});

    Thing = Backbone.RelationalModel.extend();
    Things = Backbone.Collection.extend({
        model: Thing,
        search: function(opts){
            return new Things(this.where(opts));
        }
    });

    Relationship = Backbone.RelationalModel.extend({
        relations: [
            {type: Backbone.HasOne, key: 's', relatedModel: Thing},
            {type: Backbone.HasOne, key: 'p', relatedModel: Thing},
            {type: Backbone.HasOne, key: 'o', relatedModel: Thing}
        ]
    });

    Relationships = Backbone.Collection.extend({
        model: Relationship,
        search: function(opts){
            return new Relationships(this.where(opts));
        }
    });

    things = new Things([
        new Thing({label: 'Sam', language: 'en', id: 'A', datatype: 'text'}),
        new Thing({label: 'Fred', language: 'en', id: 'D', datatype: 'number'}),
        new Thing({label: 'Jake', language: 'en', id: 'E', datatype: 'text'}),
        new Thing({label: 'Sally', language: 'en', id: 'F', datatype: 'number'}),
        new Thing({label: 'is friends with', language: 'en', id: 'B', datatype: 'text'}),
        new Thing({label: 'is working with', language: 'en', id: 'G', datatype: 'text'}),
        new Thing({label: 'Violet', language: 'en', id: 'C', datatype: 'text'})
    ]);

    relationships = new Relationships([
        new Relationship({s: "A", p: "B", o: "C"}),
        new Relationship({s: "A", p: "B", o: "D"}),
        new Relationship({s: "A", p: "B", o: "E"}),
        new Relationship({s: "A", p: "B", o: "F"}),
        new Relationship({s: "D", p: "B", o: "C"}),
        new Relationship({s: "D", p: "B", o: "F"}),
        new Relationship({s: "A", p: "G", o: "F"}),
        new Relationship({s: "D", p: "G", o: "A"})
    ]);

    MainApp.start({things: things, relationships: relationships});

    function arrUnique(field, arr){
        var all = [];
        arr.each(function(item){
            all.push(item.get(field).get('id'));
        });
        return _.uniq(all);
    }

    function graphify(arr, obj){
        var graphNew = [];
        var uniqueSubjects = arrUnique("s", arr.search({s: obj}));
        for (var i=0; i<uniqueSubjects.length; i++){

            var subject = uniqueSubjects[i];
            var newSubject = {id: subject};
            var subNodes = [];
            var uniquePredicates = arrUnique("p", arr.search({s: obj}));

            for (var j=0; j<uniquePredicates.length; j++){
                var predicate = uniquePredicates[j];
                var newPredicate = {id: predicate};
                var relatedObjects = [];
                arr.each(function(o){
                    if (o.get("s").get("id") == subject && o.get("p").get("id") == predicate){
                        relatedObjects.push({id: o.get("o").get("id")});
                    }
                });

                newPredicate.nodes = relatedObjects;
                subNodes.push(newPredicate);
            }

            newSubject.nodes = subNodes;
            graphNew.push(newSubject);
        }
        return graphNew;
    }

});

</script>

<script type="text/template" id="node-template">
    <li><label><%= JSON.stringify(id) %></label></li>
</script>

</body>
</html>
4

0 回答 0