在创建数千个子记录

时间:2016-05-27 21:24:46

标签: javascript ember.js ember-data

我是Ember.js的新手,在尝试创建数千条记录(确切地说是5300)并更新hasMany关系时遇到性能问题。我在创建新记录之前向API请求检索记录。在承诺返回之后,我然后对每个记录下来的记录(5300)执行forEach以对新记录集进行计算。创建记录本身大约需要2秒钟。更新hasMany仅对前40个左右的记录快速启动,然后减慢到每秒约一个更新。

我还应该注意,这是在一个组件内完成的。我知道这通常是anit-pattern,但在这种情况下,没有理由更改URL或转换。这是一个屏幕,用户可以从一个项目池(由路径提供)中进行选择,应用定价规则,然后根据这些项目创建一个事件(在路径中创建)。它是一个沙箱,用于确定哪些项目将成为活动的一部分。一旦用户决定了他们的活动项目,我就会向该路线发送一个动作来执行实际的保存并持续到我的后端。在反模式方面之外,我无法看到这将如何影响hasMany更新的性能。

我使用RESTAdapter和RESTSerializer来实现它的价值,但这不应该对我有任何影响,因为我只是在处理Ember数据存储。

Ember版本:

Ember             : 2.5.1
Ember Data        : 2.5.3
jQuery            : 2.2.3
Ember Simple Auth : 1.1.0

有问题的两个模型如下......

儿童模特(事件项目):

export default DS.Model.extend({
  event: DS.belongsTo('event'),
  itemNumber: DS.attr('string'),
  styleNumber: DS.attr('string'),
  tier: DS.attr('string'),
  eventPrice: DS.attr('number')
});

父模型(事件):

export default DS.Model.extend({
  eventTypeId: DS.attr('string'),
  eventName: DS.attr('string'),
  eventDesc: DS.attr('string'),
  startDate: DS.attr('moment-date'),
  endDate: DS.attr('moment-date'),
  priority: DS.attr('number'),
  statusCode: DS.attr('string'),
  value: DS.attr('number'),
  eventItems: DS.hasMany('event-item', {async:true})
});

活动创建记录:

model() {
    return this.store.createRecord('event', {});
},

负责创建记录和更新hasMany的组件中的代码块:

this.get('store').query('pricing', {brandCd: '00'}).then(tiers => {
    tiers.forEach(tier => {
        this.get('event').get('eventItems').createRecord({
            styleNumber: tier.get('styleNumber'),
            itemNumber: tier.get('itemNumber'),
            brandCd: '00',
            tier: tier.get('tier'),
            eventPrice: this._calculateEventPrice(tier.get('origPrice'), this.get('event').get('eventTypeId'), this.get('event').get('value')),
        });
    });

    this.get('event').set('needsUpdated', 'Y');
});

到目前为止,我已经尝试了以下内容......

  • 向我的hasMany和belongsTo
  • 添加反向关系
  • 将所有创建记录添加到Ember.A(),然后尝试将新记录推送到hasMany,如下所示:this.get('event').get('eventItems').pushObjects(newEventItems);。还尝试使用this.get('event').get('eventItems').addObjects(newEventItems);
  • 在正在创建的记录上设置belongsTo,而不是更新父(事件)的hasMany。
  • 我也继续前进,将这个逻辑移到我的路线上,以确保我在组件中做到这一点并不会产生奇怪的行为。它执行相同的操作。

我认为(如果我错了,请纠正我),严格在客户端创建记录和更新关系应该能够处理数千条记录而不会出现太多问题。我希望我只是做一些不正确的事情,或者以一种效率低下的方式,这对于有经验的人来说是显而易见的。任何帮助,包括替代品,都非常感谢!

1 个答案:

答案 0 :(得分:0)

我发现使用大量'hasMany'关系也很慢。

我的建议:使用自定义端点在服务器上构建关系,并通过websockets将更改传回客户端。尝试在Ember中单独保存5300条记录将产生5300个网络请求,而这可以在1个出站请求中完成,并且可能在一个websockets消息中完成,但建议以较小的集合批准响应。

在提交更改之前,无需在Ember中建立关系。返回的websockets消息应该包含关系的外键Ember Data需要构建关系。

这意味着,在没有父母的情况下,您将创建eventItems(或任何模型被调用)。

最后,您可以考虑按需创建子记录,而不是尝试立即为用户创建每个子项。当用户决定从项目池中选择项目时,只需执行createRecord。 (希望我能正确理解你的用例。)如果采用这种方法,你可能甚至不需要像我所描述的那样使用自定义端点。

最后一点建议:关于“反模式”的说明是正确的:从不在组件中进行CRUD操作或任何真正的异步操作,尤其不是 5300项。在异步操作完成之前,可以轻松地拆除组件,使应用程序处于奇怪的状态,并且很可能导致错误。像你说的那样将你做的任何事情移动到路线中,并坚持使用那种模式。组件应该只是“哑”模板,用于显示内容和发送操作。