1

对于我的 Rails 应用程序,我正在尝试使用 Searckick (elasticsearch) 设置高级搜索。我想做的事情是:

  • 可以搜索用户、位置和能力,并始终将用户配置文件作为结果返回。

到目前为止,我已经修复了它,我可以搜索用户,但我不确定如何也能够搜索这些其他模型。

我的路线:

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

一个用户属于一个位置,通过一个连接表具有多个能力。换句话说:一个用户有一个 location_id,你可以调用一个用户的 .competences 来查看用户有哪些 users_competences。

谁能告诉我如何设置这个搜索?

我的个人资料控制器:

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

我试图在我的模型中使用 def self(search),但这不起作用。

我尝试了什么:

  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
4

1 回答 1

1

TL;DR定义一种search_data自定义搜索索引的方法

self.search当前在您的代码中定义的不正确 您的self.search方法将是一种通过 ActiveRecord 和您使用的任何数据库进行搜索的方法。这不是您通过 Searchkick 进行搜索的方式。

对于 Searchkick如果您想返回与用户属性、能力和位置搜索匹配的用户配置文件,那么您应该使用以下search_data方法通过自定义映射定义您想要搜索的用户属性、能力和位置:

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

现在您在操作中的搜索查询Profiles#index将起作用:

@users = User.search(query, suggest: true, operator: "or")

不需要self.search您定义的方法。

其他注意事项

  • 我假设由于您suggest: true在查询中包含您正确定义了用户模型的建议:

    class User < ActiveRecord::Base
      searchkick locations: ["location"], suggest: [:first_name, :last_name, :location_name] # or whatever fields you want
    end
    
  • 确保重新索引
  • 因为您只想返回User对象,所以您不需要索引LocationorCompetence模型(从上面的代码中我无法判断您之前是否这样做过)
于 2016-11-22T16:30:39.577 回答