Backbone.js 模型关系:加快性能
我有三个关联模型:Segments 每个都有两个 GeoPoints,关联存储为 GeoPointOnSegments。在服务器端,这是简单的 Rails 代码,具有 has_many :through 关系。在客户端,以下是我编写的Backbone代码。 (注意:我允许客户端创建数据,然后批量上传;这就是为什么有一些逻辑来处理本地和服务器 ID。)
我发现的问题是,当我有数百个数据时,此代码非常慢模型。具体来说,它是 geo_point.coffee 中的以下行:
masterRouter.geo_point_on_segments.select ...
对每个 GeoPointOnEntry 模型进行过滤,以便找到哪些模型连接到给定的 GeoPoint。 (请注意,可以有多个段连接到一个 GeoPoint。)对于如何提高性能有什么建议吗?
我的想法:
- 利用 https://github.com/PaulUithol/Backbone-relational< 提供的功能< /a> 假设可以提供一些东西
- 在服务器端,生成嵌套的 JSON,也许有一些冗余。
- 使用 JavaScript 哈希创建某种客户端索引。
还有其他更好的想法吗?
geo_point.coffee
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')
geo_point_on_segment.coffee
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
segment.coffee
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')
I have three associated models: Segments each have two GeoPoints, with associations stored as GeoPointOnSegments. On the server side this is straightforward Rails code, with a has_many :through relationship. On the client side, the following is the Backbone code I have written. (A note: I allow for client-side creation of data and then batch upload; that's why there is some logic to deal with both local and server ids.)
The problem I am finding is that this code is very slow when I have hundreds of models. Specifically it's the following line in geo_point.coffee:
masterRouter.geo_point_on_segments.select ...
That's doing a filter on every single GeoPointOnEntry model in order to find which ones are connected to a given GeoPoint. (Note that there can be more than one Segment connected to a GeoPoint.) Any suggestions for how to improve performance?
Ideas I have had:
- Make use of functionality provided by https://github.com/PaulUithol/Backbone-relational assuming that has something to offer
- On the server-side, produce nested JSON, perhaps with some redundancy.
- Create a client-side index of sorts with a JavaScript hash.
Have any other, better ideas?
geo_point.coffee
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')
geo_point_on_segment.coffee
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
segment.coffee
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')
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为最好不要在 Backbone 中使用关系模型
GeoPointOnSegment
。我想要工作的结构是:
如果当您从 JSON 实例化数据时,您执行以下操作,那么这很容易做到:
此外,当您创建新分段时,您必须维护这些关联。
它是客户端索引,但集成在模型中。
I think it is better not to have the relation model,
GeoPointOnSegment
, in Backbone.The structure I would like to work is:
This is easy to do if, when you instantiate your data from JSON, you do something like:
Also, when you create new segments, you have to maintain these associations.
It is a client-side index, but integrated in the models.