Elastic search order by date and indexing with Ruby-on-Rails

The elastic search date field type seems like a lot of work. You have to manually map each date field parameter. All I really wanted to do was order by date, and this doesn’t necessarily ruleĀ out more complicated date range filtering. You just have to convert everything to Epoch millisecond time. Sometimes it just seems like the most standard format.

Map the field type in your elastic search index as a float. Changing a field type requires recreating the index.

mappings dynamic: 'false' do
 indexes :created_at, type: 'float'
end

In your method that converts the model to json for indexing, convert the date to milliseconds.

def as_indexed_json(options={})
  model_attrs = {
    :created_at => self.created_at.to_f
  }
end

Now you can easily order by asc and desc.

Rails 4.2 and Elastic Search – Querying and Filtering Across Multiple Nested Models

At work recently I have been working on a new filtering and search page for ourselves. The requirements were searching and filtering said search results. Things get complicated and performance tends to suffer when dealing with complicated and far reaching relationships. You end joining every table in the database and even then you are only filtering and not actually searching. Sometimes denormalized data just makes sense. It’s still a WIP but here it as anyway, hope this snippet helps you get rolling with your project.

def self.search(query="", options={})

   params = {
      query: {
        filtered: {
          query: {
            multi_match: {
              query: query,
              fields: ['title^10', 'overview']
            },
            match_all: {}
          },
          filter: {
            bool: {
              must: [
                {
                  nested: {
                    path: 'regions',
                    filter: {
                      bool: {
                        must: [
                          {
                            terms: { 'regions.id' => options[:regions] }
                          }
                        ]
                      }
                    }
                  }
                },
                {
                  nested: {
                    path: 'genres',
                    filter: {
                      bool: {
                        must: [
                          {
                            terms: { 'genres.id' => options[:genres] }
                          }
                        ]
                      }
                    }
                  }
                }
              ]
            }
          }
        }
      },
      sort: [
        {
          options[:col].try(:downcase) => {
            order: options[:direction].try(:downcase) #, ignore_unmapped: true
          }
        }
      ]
    }

    params[:query][:filtered][:query].delete(:match_all) if query.present?
    params[:query][:filtered][:query].delete(:multi_match) if query.blank?
    params.delete(:sort) if options[:col].blank? || options[:direction].blank?

    __elasticsearch__.search(params).page(options[:page]).per(options[:limit])
  end