Javascript Backbone.js模型关系:提高性能

Javascript Backbone.js模型关系:提高性能,javascript,performance,backbone.js,coffeescript,Javascript,Performance,Backbone.js,Coffeescript,我有三个关联模型:每个线段有两个地质点,关联存储为地质点线段。在服务器端,这是一个简单的Rails代码,具有has_many:through关系。在客户端,以下是我编写的主干代码。(注意:我允许客户端创建数据,然后批量上传;这就是为什么有一些逻辑来处理本地和服务器ID。) 我发现的问题是,当我有数百个模型时,这段代码非常慢。特别是geo_point.coffee中的以下行: masterRouter.geo_point_on_segments.select ... 这就是对每个单一的地质点尝试

我有三个关联模型:每个线段有两个地质点,关联存储为地质点线段。在服务器端,这是一个简单的Rails代码,具有has_many:through关系。在客户端,以下是我编写的主干代码。(注意:我允许客户端创建数据,然后批量上传;这就是为什么有一些逻辑来处理本地和服务器ID。)

我发现的问题是,当我有数百个模型时,这段代码非常慢。特别是geo_point.coffee中的以下行:

masterRouter.geo_point_on_segments.select ...
这就是对每个单一的地质点尝试模型进行过滤,以找出哪些模型连接到给定的地质点。(请注意,可以有多个线段连接到一个地质点。)关于如何提高性能有何建议

我的想法是:

  • 利用通过假设有东西可以提供而提供的功能
  • 在服务器端,生成嵌套的JSON,可能有一些冗余
  • 使用JavaScript哈希创建排序的客户端索引
还有其他更好的主意吗

geo_point.咖啡

class App.Models.GeoPoint extends Backbone.Model
  name: 'geo_point'
  getGeoPointOnSegments: ->
    masterRouter.geo_point_on_segments.select (gpos) =>
      if @isNew()
        return gpos.get('geo_point_cid') == @cid
      else 
        return gpos.get('geo_point_id') == @id
    , this
  getSegments: ->
    _.compact _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getSegment() unless gpos.get('markedForDelete')
  getConnectedGeoPoints: ->
    _.compact _.flatten _.map @getSegments(), (s) =>
      s.getGeoPoints() unless s.get('markedForDelete')
class App.Models.GeoPointOnSegment extends Backbone.Model
  name: 'geo_point_on_segment'
  getGeoPoint: ->
    if local = masterRouter.geo_points.getByCid(@get 'geo_point_cid')
      return local
    else if server = masterRouter.geo_points.get(@get 'geo_point_id')
      return server
  getSegment: ->
    if local = masterRouter.segments.getByCid(@get 'segment_cid')
      return local
    else if server = masterRouter.segments.get(@get 'segment_id')
      return server
class App.Models.Segment extends Backbone.Model
  name: 'segment'
  getGeoPointOnSegments: ->
    _.compact masterRouter.geo_point_on_segments.select (gpos) =>
      if gpos.isNew()
        return gpos.get('segment_cid') == @cid
      else if gpos.get('markedForDelete')
        return null
      else
        return gpos.get('segment_id') == @id
    , this
  getGeoPoints: ->
    _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getGeoPoint() unless gpos.get('markedForDelete')
geo\u point\u on\u细分市场。咖啡

class App.Models.GeoPoint extends Backbone.Model
  name: 'geo_point'
  getGeoPointOnSegments: ->
    masterRouter.geo_point_on_segments.select (gpos) =>
      if @isNew()
        return gpos.get('geo_point_cid') == @cid
      else 
        return gpos.get('geo_point_id') == @id
    , this
  getSegments: ->
    _.compact _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getSegment() unless gpos.get('markedForDelete')
  getConnectedGeoPoints: ->
    _.compact _.flatten _.map @getSegments(), (s) =>
      s.getGeoPoints() unless s.get('markedForDelete')
class App.Models.GeoPointOnSegment extends Backbone.Model
  name: 'geo_point_on_segment'
  getGeoPoint: ->
    if local = masterRouter.geo_points.getByCid(@get 'geo_point_cid')
      return local
    else if server = masterRouter.geo_points.get(@get 'geo_point_id')
      return server
  getSegment: ->
    if local = masterRouter.segments.getByCid(@get 'segment_cid')
      return local
    else if server = masterRouter.segments.get(@get 'segment_id')
      return server
class App.Models.Segment extends Backbone.Model
  name: 'segment'
  getGeoPointOnSegments: ->
    _.compact masterRouter.geo_point_on_segments.select (gpos) =>
      if gpos.isNew()
        return gpos.get('segment_cid') == @cid
      else if gpos.get('markedForDelete')
        return null
      else
        return gpos.get('segment_id') == @id
    , this
  getGeoPoints: ->
    _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getGeoPoint() unless gpos.get('markedForDelete')
细分市场。咖啡

class App.Models.GeoPoint extends Backbone.Model
  name: 'geo_point'
  getGeoPointOnSegments: ->
    masterRouter.geo_point_on_segments.select (gpos) =>
      if @isNew()
        return gpos.get('geo_point_cid') == @cid
      else 
        return gpos.get('geo_point_id') == @id
    , this
  getSegments: ->
    _.compact _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getSegment() unless gpos.get('markedForDelete')
  getConnectedGeoPoints: ->
    _.compact _.flatten _.map @getSegments(), (s) =>
      s.getGeoPoints() unless s.get('markedForDelete')
class App.Models.GeoPointOnSegment extends Backbone.Model
  name: 'geo_point_on_segment'
  getGeoPoint: ->
    if local = masterRouter.geo_points.getByCid(@get 'geo_point_cid')
      return local
    else if server = masterRouter.geo_points.get(@get 'geo_point_id')
      return server
  getSegment: ->
    if local = masterRouter.segments.getByCid(@get 'segment_cid')
      return local
    else if server = masterRouter.segments.get(@get 'segment_id')
      return server
class App.Models.Segment extends Backbone.Model
  name: 'segment'
  getGeoPointOnSegments: ->
    _.compact masterRouter.geo_point_on_segments.select (gpos) =>
      if gpos.isNew()
        return gpos.get('segment_cid') == @cid
      else if gpos.get('markedForDelete')
        return null
      else
        return gpos.get('segment_id') == @id
    , this
  getGeoPoints: ->
    _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getGeoPoint() unless gpos.get('markedForDelete')

我认为最好不要在主干中使用关系模型,
GeoPointOnSegment

我想工作的结构是:

  • 每个点都有一个集合及其所属的线段
  • 每个段都有一个带点的集合/数组
如果在从JSON实例化数据时执行以下操作,则很容易做到这一点:

  • 初始化所有点
  • 初始化所有段
  • 对于每个地质点段,将点添加到段的集合中,并将段添加到点的集合中。检索点和段的集合很快,因为它是按id(并按主干索引)进行的
此外,创建新线段时,必须维护这些关联


它是一个客户端索引,但集成在模型中。

我认为最好不要在主干中使用关系模型
GeoPointOnSegment

我想工作的结构是:

  • 每个点都有一个集合及其所属的线段
  • 每个段都有一个带点的集合/数组
如果在从JSON实例化数据时执行以下操作,则很容易做到这一点:

  • 初始化所有点
  • 初始化所有段
  • 对于每个地质点段,将点添加到段的集合中,并将段添加到点的集合中。检索点和段的集合很快,因为它是按id(并按主干索引)进行的
此外,创建新线段时,必须维护这些关联

它是一个客户端索引,但集成在模型中