For my Rails app I am trying to set up an advanced search with Searckick (elasticsearch). They thing I am trying to do is:
I've got it fixed so far, that I can search on a User, but I'm not sure how to be able to search on these other models as well.
My routes:
Rails.application.routes.draw do
ActiveAdmin.routes(self)
devise_for :users, controllers: {sessions: "sessions", registrations:
"registrations"}
# For details on the DSL available within this file, see
http://guides.rubyonrails.org/routing.html
root 'pages#home'
get "/news", to: 'pages#news'
get "welcome_back", to: 'pages#welcome_back'
get "/profile", to: "profile#show"
resources :profiles do
collection do
get :autocomplete
end
end
namespace :profile do
resources :locations
resources :positions
resources :competences
end
end
A user belongs to a Location, has multiple Competences through a joined table. In other words: a user has a location_id and you can call .competences on a user, to see which users_competences the User has.
Can anyone tell me how to set up this search?
My Profiles controller:
class ProfilesController < ApplicationController
def index
query = params[:search].presence || "*"
@users = User.search(query, suggest: true, operator: "or")
end
def autocomplete
render json: ["Test"]
end
end
I have tried to work with a def self(search) in my model, but this isn't working.
What I tried:
def self.search(search)
where(["User.first_name LIKE ?","%#{search}%"])
where(["User.last_name LIKE ?","%#{search}%"])
where(["User.competences.collect{&:name} IN ?","%#{search}%"])
joins(:location).where("location.name LIKE ?", "%#{search}%")
else
all
end
end
TL;DR define a search_data
method to customize your search index
self.search
as currently defined in your code is incorrect
Your self.search
method would be a way to search via ActiveRecord and whatever database you are using. It is not how you search via Searchkick.
For Searchkick If you want to return User profiles that match searches for user attributes, competences, and locations then you should define the user attributes, competences, and locations that you want to search via custom mappings using the search_data
method, documented here:
class User < ActiveRecord::Base
searchkick locations: ["location"]
# this line will eager load your assocations
scope :search_import, -> { includes(:location, :competences) }
def search_data
{
first_name: first_name,
last_name: last_name,
competences: competences.map(&:name),
# from your code above it looks like you want to search location.name
location_name: location.name
# the following merged hash would allow you to search by location latitude and
# longitude coordinates if you have them
## if you don't use latitude and longitude then you don't need to include
## `locations: ["location"] when you call searchkick in the User model on line 2
## above or the merged location hash below
}.merge(location: {lat: location.latitude, lon: location.longitude})
end
end
Now your search query in the Profiles#index
action will work:
@users = User.search(query, suggest: true, operator: "or")
There is no need for the self.search
method that you defined.
Other Notes
I assume since you included suggest: true
in your query that you defined suggestions on your user model correctly:
class User < ActiveRecord::Base
searchkick locations: ["location"], suggest: [:first_name, :last_name, :location_name] # or whatever fields you want
end
User
objects then you don't need to index the Location
or Competence
models (from your code above I couldn't tell if you did previously)