LMH
LMH

Reputation: 949

Elastic Search Multiple Fields

I'm using Tire to index and search a database of cars:

create :mappings => {
    :cars => {
        :properties => {
            :id => {:type => 'string', :index => 'not_analyzed', :include_in_all => true},
            :user_id => {:type => 'string', :index => 'not_analyzed'},
            :name => {:type => 'string', :analyzer => 'snowball' },
            :time => {:type => 'long', :index => 'not_analyzed'},
            :origin_country => {:type => 'string', :analyzer => 'keyword', :include_in_all => false},
            :origin_state => {:type => 'string', :analyzer => 'keyword', :include_in_all => false},
            :origin_city => {:type => 'string', :analyzer => 'keyword', :include_in_all => false},
            :dealer_name => {:type => 'string', :analyzer => 'snowball', :boost => 1.5, :include_in_all => false}
        }
    }
}

And queries look like:

   s = Tire.search Search.index_name do

      query do |query|
        query.text :_all, downcased_query, :type => :phrase
      end

    end

Right now if you search for "New York Joe Dealer" it will match if there is a dealer_name is "Joe Dealer" or if the origin_state is "New York" but not both. Is there a way to match origin_state is "New York" and "dealer_name" is "Joe Dealer" (or either)? The idea is I want a user to enter in a fre-form query string and be able to find the best matches possible and to a user they would expect to enter New York Joe Dealer and find all cars sold at Joe Dealer in New York (or all cars in New York or at Joe Dealer ranked lower).

Upvotes: 0

Views: 677

Answers (2)

karmi
karmi

Reputation: 14419

The correct solution would be to use the multi_match query to perform the same query against multiple fields. It's supported in Tire, see https://github.com/karmi/tire/blob/master/test/integration/match_query_test.rb.

Tire.search Search.index_name do
  query do |query|
    query.match :dealer_name, downcased_query
    query.match :origin_state, downcased_query
  end
end

You can even use the phrase type if the query would contain both the dealer and state info in correct order, such as "New York Joe Dealer".

Upvotes: 2

LMH
LMH

Reputation: 949

The solution was to move to a "match" type filter, and diable :type => :phrase, so:

query do |query|
    query.match :_all, downcased_query
end

There are still some issues with sorting so that time is still a big input, but this resolves many of the issues.

Upvotes: 0

Related Questions