diff --git a/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb b/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb index 30d851043..7e91b6962 100644 --- a/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb +++ b/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb @@ -106,17 +106,15 @@ def __ids_by_type # @api private # def __type_for_hit(hit) - @@__types ||= {} - key = "#{hit[:_index]}::#{hit[:_type]}" if hit[:_type] && hit[:_type] != '_doc' - key = hit[:_index] unless key - - @@__types[key] ||= begin - Registry.all.detect do |model| - (model.index_name == hit[:_index] && __no_type?(hit)) || - (model.index_name == hit[:_index] && model.document_type == hit[:_type]) - end + key = if hit[:_type] && hit[:_type] != '_doc' + "#{hit[:_index]}::#{hit[:_type]}" + else + hit[:_index] end + + # DVB -- #838, refactor the lookup of index name to model into the Registry + Registry.lookup(key, hit[:_type]) end def __no_type?(hit) diff --git a/elasticsearch-model/lib/elasticsearch/model/multimodel.rb b/elasticsearch-model/lib/elasticsearch/model/multimodel.rb index 6b5fc2a81..d71c44552 100644 --- a/elasticsearch-model/lib/elasticsearch/model/multimodel.rb +++ b/elasticsearch-model/lib/elasticsearch/model/multimodel.rb @@ -19,10 +19,11 @@ module Elasticsearch module Model # Keeps a global registry of classes that include `Elasticsearch::Model` - # + # Keeps a global registry of index to class mappings class Registry def initialize @models = [] + @indexes = {} end # Returns the unique instance of the registry (Singleton) @@ -45,10 +46,29 @@ def self.all __instance.models end + def self.indexes + __instance.indexes + end + + def self.add_index(index, model) + __instance.add_index(index, model) + end + # Adds a model to the registry # def add(klass) - @models << klass + # Detect already loaded models and ensure that a duplicate is not stored + if i = @models.index{ |_class| _class.name == klass.name } + @models[i] = klass + # clear the cached index map (autoloading in development causes this) + @indexes.clear + else + @models << klass + end + end + + def add_index(index, model) + @indexes[index] = model end # Returns a copy of the registered models @@ -56,6 +76,34 @@ def add(klass) def models @models.dup end + + def indexes + @indexes.dup + end + + ## + # Find the model matching the given index and document type from a search hit + # Cache the index->model mapping for performance + # Clear the index cache when models are reloaded + def self.lookup(index, type=nil) + if Registry.indexes.has_key?(index) + # Cache hit + Registry.indexes[index] + else + # Cache bust + model = if type.nil? or type == "_doc" + # lookup strictly by index for generic document types + Registry.all.detect{|m| m.index_name == index} + else + # lookup using index and type + Registry.all.detect{|m| m.index_name == index and model.document_type == type} + end + # cache the index to model mapping + Registry.add_index(index, model) + model + end + end + end # Wraps a collection of models when querying multiple indices