1

I'm a Rails developer. I've been tasked with upgrading Elasticsearch from 0.9 in a large and very old Rails application.

This application, in its current state, runs on Elasticsearch 0.90.7 and is using the retired gem Tire. I'll be switching to the officially supported elasticsearch-ruby (and elasticsearch-model) gems, but in the mean time, I need to address breaking changes in the index definitions, which are defined in the Rails models.

My problem is that I don't understand how Tire (or Elasticsearch - not sure what's doing what here) is defining the mappings of classes that inherit from a class with an explicitly defined mapping block.

So, the code:

There's one model that has a ton of children. 'Tag' can be of many types. So the mapping looks like this:

class Tag < ActiveRecord::Base
  mapping do
    # some mappings that aren't causing me any problems

    # and then there's these guys
    indexes :name, analyzer: 'snowball', boost: 100
    indexes :type

    # more mappings that are happily being good, understandable mappings
  end
end

And we have some different types of tags:

class ATagType < Tag
  # absolutely no code regarding mappings, index definition, or the like
end

class BTagType < Tag
  # still no code regardining mappings, index definitions, or the like
end

class CTagType < Tag
  # ... just, yeah. nothing helpful here either.
end

So when I run Tag.create_elasticsearch_index and then look at the new index that's been created (just adding in the relevant properties for now):

$ $elasticsearch.indices.get_mapping["application_development_tags"]
=> { "tag" => {
           "properties" => {
             "name" => { "type" => "string", "boost" => 100.0, "analyzer" => "snowball" },
              "type" => { "type" => "string" }
           }
         }
       }

And then I run Tag.import in order to index all of the tags in the database.

This changes the "application_development_tags" index mapping:

$ $elasticsearch.indices.get_mapping["application_development_tags"]
=> { "tag" => {
           "properties" => {
             "name" => { "type" => "string", "boost" => 100.0, "analyzer" => "snowball" },
             "type" =>  { "type" => "string" }
           }
         },
         "atagtype" => {
           "properties" => {
             "name" => { "type" => "string" },
             "type" => { "type" => "string" }
           }
         },
         "btagtype" => { etc. }
        }

And this is the way the index currently exists on production.

Then in upgrading, I've run into an issue regarding the fact that different types of an index have the same property ("name") with different "boost" and "analyzer" settings.

Thing is, I cannot for the life of me figure out what code is re-shaping the index after importing all tags. I think indexes :type is probably the culprit, and I read the conversion of class type into Elasticsearch index type as a feature. But then, why isn't the name for every type of tag that inherits from Tag mapped in the same way as "tag"? The ideal situation makes it so that all tags and all of its children have the same analyzer and boost, as this would maintain current behavior (or as close to current behavior as we're going to get) and make it so I can recreate the indices in the newer version of Elasticsearch.

I've tried explicitly adding the mapping do block to each of the Tag model's children - but that doesn't change behavior at all (not calling TagType1.create_elasticsearch_tag and so the mapping definition in TagType1 is ignored). If I remove the analyzer and boost definition from the Tag mapping, everything is good, but... I'm pretty sure we still want the analyzer and boost, and it'd be better to add them to all tag types than get rid of them entirely. (Related: this - but the provided 'answer' really doesn't actually address the problem).

To make this more complicated, I've listed all of the properties in all of the TagTypes, and each type has different properties from the originally defined "tag" type.

So is there anybody who might be able to help me figure out what's going on, and successfully recreate my indices in the newer versions of Elasticsearch?

Edit

Something else I just learned: Tag.import changes the mapping of application_development_tags but $elasticsearch.search type: 'application_development_tags', type: 'tag returns no results. Only searching by the other types actually returns results.

wendybeth
  • 424
  • 4
  • 17

0 Answers0