Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi-index search #38

Closed
codker opened this issue Sep 30, 2013 · 26 comments
Closed

multi-index search #38

codker opened this issue Sep 30, 2013 · 26 comments

Comments

@codker
Copy link

codker commented Sep 30, 2013

Searchkick should support multi-index search.

I have overcome this by using:

Model1.search("thequery", index_name: [Model1.index.name, Model2.index.name, Model3.index.name])

it works ok, but it's just wrong to have to do this.

Maybe the starting point can be #36?

@ankane
Copy link
Owner

ankane commented Oct 1, 2013

Multi-index search would be nice. What are your thoughts on the best way to declare indexes?

@codker
Copy link
Author

codker commented Oct 1, 2013

(fixed the example above, was missing 'index.name' calls)

what about something this:

Searchkick.search("thequery", [Model1, Model2, Model3], other_options)

@aman199002
Copy link

Is this method still pending to search across multiple models. I want to use boost and autocomplete across multiple models. If searching on a particular model using index names like:

Model1.search("thequery", index_name: [Model1.index.name, Model2.index.name], boost: 'name')

then, boost will be applied only for that Model1. How can i use boost across multiple models. Like in tire, we can define it while indexing in mapping.

@jamsi
Copy link

jamsi commented Feb 19, 2014

Quick (perhaps silly) question, how can I get the index name for a model?

@ankane
Copy link
Owner

ankane commented Feb 19, 2014

It's now Model.searchkick_index.name.

@jamsi
Copy link

jamsi commented Feb 19, 2014

Holy moly that was a fast response. Much appreciated.

@ankane
Copy link
Owner

ankane commented Feb 19, 2014

Haha, no problem - right place, right time.

@jamsi
Copy link

jamsi commented Feb 19, 2014

Ok second question; how can I get the current full index name?

Test.searchkick_index.name is returning "test_development"

But my actual index_name is "test_development_20140219162300398" etc. I need the full name in order to use it alongside index_name: when searching across multiple models.

@ankane
Copy link
Owner

ankane commented Feb 19, 2014

You should use the alias when searching across models - it's more robust and gives you the same results.

@jamsi
Copy link

jamsi commented Feb 19, 2014

Ah my bad, I had mistyped an index name. Thanks again.

@ankane ankane added the 1.0 label Mar 5, 2014
@armstrongnate
Copy link

+1 to multi-index search. @liberatiluca's suggestion would be awesome.

@amenzhinsky
Copy link

The workaroud which is on the very top of the page doesn't work because index_name option is useless now. Index name is set explicitly index: searchkick_index.name before sending to client

@jdurand
Copy link
Contributor

jdurand commented Mar 27, 2014

I used this for an autocomplete field to match multiple models (indexes) :

results = []

[Model1, Model2, Model3, Model4].each do |model|
  query = Searchkick::Query.new model, params[:query], load: false, fields: [{name: :text_start}], limit: 10
  results = results.concat query.execute.response['hits']['hits']
end

results.sort_by! { |r| r['_score'] }.reverse!

render json: {
  all: results.map { |r| { value: r['_source']['name'] } }.first(10)
}

It shouldn't be too much of a hastle to add a method that uses this logic to the Searchkick::Query class. I'll take a deeper look into this when I have the time.

@ankane
Copy link
Owner

ankane commented Mar 29, 2014

@amenzhinsky Oops, just fixed. Need to add a test for that. cec8c58

@jdurand What's the advantage to this approach vs the index_name option?

@jdurand
Copy link
Contributor

jdurand commented Mar 30, 2014

@ankane I never got the index_name approach to work and, if I understood correctly, this approach would not let you define different search criterion (ie: boost) for each model.
My approach does 4 separate queries and assemble the results, so we could do something like :

[{model: Model1, boost: 'popularity'}, {model: Model2, boost: 'popularity'}].each do |params|
  ...

I'm just tossing ideas around...

@ahmetabdi
Copy link

Has this been implemented into searchkick yet?

@oliyoung
Copy link

Another solution for the multimodel search (this will search across all searchkick indexes)
index_name: Searchkick.client.indices.get_aliases.keys,

@Madumo
Copy link

Madumo commented Jan 23, 2015

Is it possible to specify an includes option for each model type doing a multisearch that way?

@mnorhamizan
Copy link

Hi,
I'm a beginner with rails

Model1.search(params[:query], index_name: [Model1.searchkick_index.name, Model2.searchkick_index.name])

I tried using it like this but all the results comes only from Model1. Is there anyway to get results from both models.

Both models have different attributes.

@tomav
Copy link

tomav commented Mar 19, 2016

👍

@RyanSnodgrass
Copy link

RyanSnodgrass commented May 20, 2016

The solution I have found comes from using the Searchkick class as my method

# app/models/foo.rb
class Foo
  searchkick
  def search_data
    { name: name }
  end
  def name
  end
end

# app/models/bar.rb
class Bar
  searchkick
  def search_data
    { name: name }
  end
  def name
  end
end
> Foo.reindex
> Bar.reindex
results = Searchkick.search('query')

This will search every index with the name field.


If you want to search just specific fields

# update the `search_data` method to contain your other field
# app/models/foo.rb
class Foo
  searchkick
  def search_data
    { name: name,
      description: description }
  end
  def name
  end
  def description
  end
end
> Foo.reindex
# you can then define which fields to search
results = Searchkick.search('query', fields: ['name', 'description'])

# Cool part is, if one model/index has a field the others don't, searchkick will still work as expected
results = Searchkick.search('query', fields: ['name', 'description', 'unique_field'])

# if you want to boost a certain field, put a carrot to power
results = Searchkick.search('query', fields: ['name^10', 'description'])

@MrHubble
Copy link

MrHubble commented Sep 7, 2016

This feature was added to the documentation in July: bd12de7

I'm unsure when the code was implemented.

Does anyone know if it's possible to search multiple indices (ie Searchkick.search "milk", index_name: [Product, Category]) and apply different order and limit to the different indices?

@ankane
Copy link
Owner

ankane commented Sep 8, 2016

@MrHubble You'll need use multi search instead (basically, two separate queries) if you want different orders and limits.

https://github.com/ankane/searchkick#multi-search

@ankane
Copy link
Owner

ankane commented Sep 8, 2016

Closing this issue as multi-index search is now supported. Please create a new issue if I missed anything or there are future questions.

@ankane ankane closed this as completed Sep 8, 2016
@apuntovanini
Copy link

@ankane Sorry to bother, but how can I sort results by _score in a multi_search example?

user_results = User.search(
  "*",
  limit: 20,
  execute: false
)
organization_results = Organization.search(
  "*",
  limit: 40,
  execute: false,
  order: { updated_at: :desc}
)
Searchkick.multi_search([user_results, organization_results])

I'd like to see organizations with higher score before than users. Thanks in advance

@ankane
Copy link
Owner

ankane commented Oct 6, 2016

You'll need to do this in Ruby. Also, as mentioned in the comment above, please create a new issue for new questions so the 15 other subscribers to this issue aren't spammed.

@lock lock bot locked as resolved and limited conversation to collaborators Dec 29, 2018
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests