2

I'm using elastic search to enhance search capabilities in my app. Search is working perfectly, however sorting is not for fields with multiple words.

When I try to sort the search by log 'message', I was getting the error:

"Can't sort on string types with more than one value per doc, or more than one token per field"

I googled the error and find out that I can use multi-fields mapping on the :message field (one analyzed and the other one not) to sort them. So I did this:

class Log < ActiveRecord::Base
  include Tire::Model::Search
  include Tire::Model::Callbacks

  tire.mapping do
    indexes :id, index: :not_analyzed
    indexes :source, type: 'string'
    indexes :level, type: 'string'
    indexes :created_at, :type => 'date', :include_in_all => false
    indexes :updated_at, :type => 'date', :include_in_all => false
    indexes :message, type: 'multi_field', fields: { 
      analyzed: {type: 'string', index: 'analyzed'},
      message: {type: 'string', index: :not_analyzed} 
    }
    indexes :domain, type: 'keyword'
  end
end

But, for some reason is not passing this mapping to ES.

rails console
Log.index.delete #=> true
Log.index.create #=> 200 : {"ok":true,"acknowledged":true}
Log.index.import Log.all #=> 200 : {"took":243,"items":[{"index":{"_index":"logs","_type":"log","_id":"5 ... ...

# Index mapping for :message is not the multi-field 
# as I created in the Log model... why?

Log.index.mapping
=> {"log"=>
  {"properties"=>
    {"created_at"=>{"type"=>"date", "format"=>"dateOptionalTime"},
     "id"=>{"type"=>"long"},
     "level"=>{"type"=>"string"},
     "message"=>{"type"=>"string"},
     "source"=>{"type"=>"string"},
     "updated_at"=>{"type"=>"date", "format"=>"dateOptionalTime"}}}}

# However if I do a Log.mapping I can see the multi-field
# how I can fix that and pass the mapping correctly to ES? 

Log.mapping
=> {:id=>{:index=>:not_analyzed, :type=>"string"},
 :source=>{:type=>"string"},
 :level=>{:type=>"string"},
 :created_at=>{:type=>"date", :include_in_all=>false},
 :updated_at=>{:type=>"date", :include_in_all=>false},
 :message=>
  {:type=>"multi_field",
   :fields=>
    {:message=>{:type=>"string", :index=>"analyzed"},
     :untouched=>{:type=>"string", :index=>:not_analyzed}}},
 :domain=>{:type=>"keyword"}}

So, Log.index.mapping is the current mapping in ES which doesn't contain the multi-field that I created. Am I missing something? and why the multi-field is shown in Log.mapping but not in Log.index.mapping?

1 Answer 1

5

I have changed the workflow from:

Log.index.delete; Log.index.create; Log.import

to

Log.index.delete; Log.create_elasticsearch_index; Log.import

The MyModel.create_elasticsearch_index creates the index with proper mapping from model definition. See Tire's issue #613.

Sign up to request clarification or add additional context in comments.

1 Comment

Running these in a rails console also made it easy for me to diagnose an error that was preventing my index from being updated so thanks for that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.