У меня есть три связанные модели: Сегменты каждая имеет две GeoPoints , с ассоциациями, сохраненными как GeoPointOnSegments . На стороне сервера это простой код Rails с отношением has_many: through. На стороне клиента ниже приведен код Backbone, который я написал. (Примечание: я допускаю создание данных на стороне клиента, а затем пакетную загрузку; поэтому существует некоторая логика для работы с локальными и серверными идентификаторами.)
Проблема, которую я нахожу, состоит в том, что этот код очень медленный, когда у меня сотни моделей. В частности это следующая строка в geo_point.coffee:
masterRouter.geo_point_on_segments.select ...
Это делает фильтр для каждой модели GeoPointOnEntry, чтобы найти, какие из них связаны с данной GeoPoint. (Обратите внимание, что к GeoPoint может быть подключено несколько сегментов.) Есть предложения по улучшению производительности?
У меня были идеи:
- Используйте функциональные возможности, предоставляемые https://github.com/PaulUithol/Backbone-relational, предполагая, что есть что предложить
- На стороне сервера создайте вложенный 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')