【问题标题】:Ember Data nested ModelsEmber 数据嵌套模型
【发布时间】:2013-10-08 09:31:54
【问题描述】:

我在使用 NDB 的 Google App Engine 项目中使用 EmberJs 和 Ember-Data。在数据库中,我有 Host、Probe 和 Check 实体。只要我的 REST api 有序,数据库模型并不重要,但为了清楚起见,这里是我的数据库类:

class Host(ndb.Model):
    hostName = ndb.StringProperty()

hostKey = ndb.Key('Host', 'SomeHostId')

class Probe(ndb.Model):
    checkName = ndb.StringProperty()

probeKey = ndb.Key('Host', 'SomeHostId', 'Probe', 'SomeProbeId')

class Check(ndb.Model):
    checkName = ndb.StringProperty()

checkKey = ndb.Key('Host', 'SomeHostId', 'Probe', 'SomeProbeId', 'Check', 'SomeCheckId')

我添加了键以显示每个主机都有一些正在运行的探测器,并且每个探测器都执行一些检查。

  • 主机
    • 探头
      • 检查

在我的 App.Js 中,我定义了以下模型:

App.Host = DS.Model.extend({
    hostName: DS.attr('string')
    probes: DS.hasMany('probe',{async:true})
});

App.Probe = DS.Model.extend({
    host: DS.belongsTo('host'),
    probeName: DS.attr('string')
    checks: DS.hasMany('check',{async:true})
});

App.Check = DS.Model.extend({
    probe: DS.belongsTo('probe'),
    hostName: DS.attr('string')
});

我已经定义了以下路由器:

App.Router.map(function() {
    this.resource('hosts', function(){
        this.resource('host', { path:':host_id'}, function(){
            this.resource('probes', function(){
                this.resource('probe', { path:':probe_id'}, function(){
                    this.resource('checks', function(){
                        this.resource('check', { path:':check_id'}, function(){

                        });
                    });
                });
            });
        });
    });
});

如果在 AppEngine 中构建了以下 URL 路径:

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    webapp2.Route('/hosts', HostsHandler),
    webapp2.Route('/hosts/<hostId>/', HostHandler),
    webapp2.Route('/hosts/<hostId>/probes', ProbesHandler),
    webapp2.Route('/hosts/<hostId>/probes/<probeId>/checks', ChecksHandler),
    webapp2.Route('/hosts/<hostId>/probes/<probeId>/checks/<checkId>/', CheckHandler)
])

http://example.com/hosts 返回:

{
    "hosts": [
        {
            "hostName": "SomeHostName1",
            "id": "SomeHostId1"
        },
        {
            "hostName": "SomeHostName2",
            "id": "SomeHostId2"
        }
    ]
}

http://example.com/hosts/SomeHostId1/probes 返回:

{
    "probes": [
        {
            "probeName": "SomeProbeName1",
            "id": "SomeProbeId1",
            "host_id": "SomeHostId1"
        },
        {
            "probeName": "SomeProbeName2",
            "id": "SomeProbeId2",
            "host_id": "SomeHostId1"
        }
    ]
}

http://example.com/hosts/SomeHostId1/probes/SomeProbeId1/checks 返回:

{
    "checks": [
        {
            "checkName": "SomeCheckName1",
            "id": "SomeCheckId1",
            "probe_id": "SomeProbeId1"
        },
        {
            "checkName": "SomeCheckName2",
            "id": "SomeCheckId2",
            "probe_id": "SomeProbeId1"
        }
    ]
}

我的模板是:

<script type="text/x-handlebars" id="host">
  <h3>{{hostName}}</h3>
  {{#link-to 'probes' probes}}probes{{/link-to}}

  {{outlet}}
</script>

<script type="text/x-handlebars" id="probes">
  {{#each probe in probes}}
    Probe: {{probe.probeName}}
    {{#link-to 'checks' probe.checks}}checks{{/link-to}}
  {{/each}}

  {{outlet}}
</script>

<script type="text/x-handlebars" id="checks">
  {{#each check in checks}}
    Check: {{check.checkName}}
  {{/each}}
</script>

现在我拥有了所有这些......但不知道如何将它们捆绑在一起,以便 Ember-Data 发出正确的 http 请求。到目前为止,我只看到请求转到http://example.com/modelName/

【问题讨论】:

    标签: ember.js ember-data


    【解决方案1】:

    目前 Ember Data 不支持 API 端点的这种类型的嵌套路由。对此进行了一些讨论,但似乎没有取得任何进展。

    【讨论】:

    • 嵌入记录和嵌套 API 路由是完全不同的两件事。
    • 我先让这个问题获得更多观点,然后接受您的回答。我只是添加赏金以获得更多关注。希望它有所帮助;)
    【解决方案2】:

    我对 App 引擎一无所知,但如果你能获得这样的配置,用于 ember-data rest 适配器

    app = webapp2.WSGIApplication([
        ('/', MainHandler),
        webapp2.Route('/hosts', HostsHandler),
        webapp2.Route('/hosts/<hostId>', HostHandler),
        webapp2.Route('/probes', ProbesHandler),
        webapp2.Route('/probes/<probeId>', ProbesHandler),
        webapp2.Route('/checks/', CheckHandler)
        webapp2.Route('/checks/<checkId>/', CheckHandler)
    ])
    

    http://example.com/hosts 的响应应该返回一个 json 数组 hosts:[{},{}] 和对 http://example.com/hosts/1 一个代表主机对象 host:{} 的 json 并且对于其他 AppEngine 路由也是如此

    【讨论】:

    • 一次加载所有检查可能不是一个好主意。为了清楚起见,我保留了一层嵌套(checkDataItems)。我有这样的情况,我们有 1000 多台主机运行 1 次以上的探测,运行 15 次以上的检查。每张支票可以有1-20个数据项。如果我只得到检查,它可能运行正常。但是,如果我同时加载所有 checkDataItems ......这可能需要一段时间。
    • 您可以将参数添加到查询中,并在您的 chechks 路由模型挂钩中使用类似 store.findQuery('check', { probe_id: "1" }).then() 的内容点击 example.com/checks?probe_id=1
    • 是的,那是我的备份实现。
    【解决方案3】:

    您已经定义了两次 Host 模型,我认为不应该是这样。我对 ember 很陌生,还没有使用 async:true 功能,但我已经能够做类似的事情(但我没有使用嵌套路由):

    App.Host = DS.Model.extend({
        hostName: DS.attr('string')
        probes: DS.hasMany('probe')
    });
    
    App.Probe = DS.Model.extend({
        probeName: DS.attr('string')
        checks: DS.hasMany('check')
    });
    
    App.Check = DS.Model.extend({
        checkName: DS.attr('string')
    });
    

    你可以为返回的主机启动一个 rest api:

    {
        "hosts": [
            {
                "hostName": "SomeHostName1",
                "id": "SomeHostId1",
                "probes":["p1","p2"]
            },
            {
                "hostName": "SomeHostName2",
                "id": "SomeHostId2",
                "probes":["p2","p3"]
            }
        ],
        "probes": [
            {
                "probeName": "SomeProbeName1",
                "id": "p1",
                "checks":["c1","c2"]
            },
            {
                "probeName": "SomeProbeName2",
                "id": "p2",
                "checks":["c2","c3"]
            }
        ],
        "checks": [
            {
                "checkName": "SomeCheckName1",
                "id": "c1"
            },
            {
                "checkName": "SomeCheckName2",
                "id": "c2"
            }
        ]
    } 
    

    在我的情况下,我没有嵌套路由,但我认为我们应该能够以某种方式从主有效负载设置控制器内容,因为所有必需的内容都已经存储了!我不知道它是否有任何帮助,但这也是我想知道的答案。

    【讨论】:

    • 添加子实体的 ID 将花费我第二次数据库查询,因为您不能(也不应该)在谷歌数据存储中进行连接。但是,我认为运行第二个查询可能是可以接受的,因为我只要求 id 属性。
    • PS 你是对的,它应该是一个检查模型。我现在已经更新了帖子:)
    • 我正在尝试与您的答案相同,但我还没有运行代码......控制器看起来像什么? ember 文档中的 AFAICT 控制器只代表一个模型类(单个对象或相同类型的列表)
    • 给定的 json 结构将是 HugsController 的底层模型/内容,这将是一个 ArrayController,因此 json 结构包含多个主机(以及与之关联的所有探测器/检查)。如果您正在考虑单个主机,那么您将创建一个 HostController 它将是一个 ObjectController 并且底层 json(model) 将是 {"host":{"hostName":..., "probles":["p1 ","p2"]}, "探针":[{"id":"p1",...}, {"id":"p2",...}}]}。希望你明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多