class Product < ActiveRecord::Base
belongs_to :city
has_and_belongs_to_many :categories
before_destroy { categories.clear }
searchkick locations: ["location"]
def search_data
{
istatus: i_status,
name: name,
price: price,
city_id: city_id,
value: value,
discount: discount,
expiry_date: expiry_date,
created_at: created_at,
products_sold: products_sold,
city: city.name,
deal_type: deal_type,
country: city.country.name,
category_id: categories.map(&:id),
location: [latitude, longitude]
}
end
def self.apply_filters(request)
# #product = Product.search "Tex-Mex", limit:10 #=>this works
#product = Product.search body: {match: {name: "Tex-Mex"}},limit: 10 #=>does not work, the limit part work
end
end
when i use advanced search using body.. it does not return the desired results although the limit:10 part us working as it does return 10 results only
I believe there is some missing information in the documentation.
Here's a reference to a body query that works based on the tests written in SearchKick:
https://github.com/ankane/searchkick/blob/c8f8dc65df2e85b97ea508e14ded299bb8111942/test/index_test.rb#L47
For advanced search to work, the way it should be written is:
#product = Product.search body: { query: { match: {name: "Tex-Mex"}}},limit: 10
You need a query key following the body.
// conditions = {}
query = Product.search params[:query], execute: false, where : conditions
query.body[:query] = { match: {name: "Tex-Mex"} }
query.body[:size] = 10
query.execute
You would need to build your query using the Elasticsearch DSL. Specifically, using size and match.
Product.search body: { query: { match: {name: "Tex-Mex"} }, size: 10 }
When using Advanced search, Searchkick ignores parameters outside the body hash. While the body hash allows you to use the full ES DSL.
Related
I am using elasticsearch-rails gem in my rails application. Everything is setup, but i am having trouble when i search two words with space between them.
Here is my code:
SEARCH_FIELDS = %w"name email"
attribute :text, type: String, default: ''
response = MyModelName.search([query, filter, sort].compact.reduce(:merge)).page(page).per(per_page)
def query
query = {}.tap do |q|
q[:query_string] = {query: text, default_operator: 'AND', fields: SEARCH_FIELDS, allow_leading_wildcard: true}
end
return {query: query}
end
def filter
filters = []
filters << {term: {user_id: user_id}}
filters << {term: {hide: (hide.nil? ? false : hide)}}
return {filter: {and: filters}}
end
If i search first initials of name like ('John') that works fine, but name with space('John doe') did not get found.
make sure you're building the right syntax for your query, is you want exact match in ES you must set query between qoutes
search_field:"daniel acevedo"
{
"size": 10,
"query": {
"query_string": {
"query": "search_field:\"daniel acevedo\""
}
}
}
I have added a new field to searchkick, and can get the results to return for that model but I am trying to find the parent model as a result.
People can have many tags. I can search for People just fine by any attribute that exist on that schema. I can search for Tags just fine and searchkick and elasticsearch will return the result.
I want to search by the tag name and then return the people associated with that result
search_query = if #q.present?
{
query: {
multi_match: {
query: #q.strip.downcase,
fields: %w(first_name last_name email_address phone_number address_1 name),
type: 'cross_fields',
operator: 'AND'
}
}
}
else
{
query: {
query_string: {
query: ('*'),
default_operator: 'AND'
}
},
# order: { signup_at: :desc },
# page: search_params[:page],
# per_page: (Kaminari.config.default_per_page unless request.format == :csv)
}
end
#results = Person.search search_query
#people = #results.records.where(active: true).order("people.#{sort_column}" + ' ' + sort_direction).page(search_params[:page])
This currently works fine for searching people only attributes. If I replace
#results = Tag.search search_query When inputting a tag name I get the resulting tag.
An older query was in place that worked fine, but had to be changed to allow full name searching. The old query was
query: {
query_string: {
query: (#q.strip.downcase),
default_operator: 'AND'
}
},
And that returned the associated tags with the rest of the code remaining unchanged.
Here is the search_data method that exist on the person model` # For Searchkick
def search_data
attributes.
each { |_k, v| v.downcase if v.is_a? String }.
merge({
tag: tags.map { |t| t.name.downcase },
trait: traits.map { |t| t.name.downcase },
trait_value: person_traits.map { |pt| pt.value.downcase },
question: questions.map(&:id),
answer: answers.map { |a| a.value.downcase },
last_participated: last_participation_date.to_s,
signup_at: signup_at.to_s
})
end
Please let me know if I can provide other information to help.
Since you have tags in the search_data method on Person, you can do:
Person.search("sometag", fields: [:tag])
Make sure your search_data method returns correct data with:
Person.first.search_data
And make sure you have reindexed.
Person.reindex
I have a Rails4 app using elasticsearch and searchkick for a sitewide search page.
I have configured the models and its associations using searchkick search_data, but its not working as per my requirement where user can search all venues by location, name, capacity, event(marriage, engagements etc.) and food_type(veg/non-veg). So precisely when i search for venues with required params, i still didnt get the desired result.
Below is the elasticsearch query in the server...
[SITE WIDE SEARCH] **************SEARCH QUERY***["new", "Mumbai, Maharashtra", "3000", "VEG", "BUSINESS MEETING"]******************
Venue Search (7.2ms) curl http://localhost:9200/venues_development/_search?pretty -d '{"query":{"bool":{"must":{"dis_max":{"queries":[{"match":{"_all":{"query":"Mumbai, Maharashtra","boost":10,"operator":"and","analyzer":"searchkick_search"}}},{"match":{"_all":{"query":"Mumbai, Maharashtra","boost":10,"operator":"and","analyzer":"searchkick_search2"}}},{"match":{"_all":{"query":"Mumbai, Maharashtra","boost":1,"operator":"and","analyzer":"searchkick_search","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true}}},{"match":{"_all":{"query":"Mumbai, Maharashtra","boost":1,"operator":"and","analyzer":"searchkick_search2","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true}}}]}},"filter":[{"range":{"capacity_in_persons":{"to":"3000","include_upper":true}}},{"term":{"food_type":"VEG"}},{"term":{"event_type_name":"BUSINESS MEETING"}}]}},"size":1000,"from":0,"timeout":"11s","_source":false}'
models/venue.rb:
##columns of venue.rb
##=> Venue(id: integer, name: string, description: text,active: boolean, announcements_count: integer, comments_count: integer, pictures_count: integer, videos_count: integer, created_at: datetime, updated_at: datetime, capacity_in_persons: string, workflow_state: string)
### associations
has_many :event_categories
has_many :event_types, through: :event_categories
has_one :address, :as=> :addressable, :dependent => :destroy
###elasticsearch config starts here
searchkick word_middle:["name^10", :slug, :capacity_in_persons], locations: ["location"]
def search_data
{
name: name, analyzer: 'english', #: :word_start, misspellings: false},
capacity_in_persons: capacity_in_persons,
food_type: food_type,
slug: slug,
##has many event types
event_type_name: event_types.map(&:name),
ratings: ratings.map(&:stars),
##location: [self.address.latitude, self.address.longitude],
location: [self.address.latitude, self.address.longitude],
picture_url: pictures.select{|p| p == pictures.last}.map do |i|{
original: i.original_url
}
end
}
end
##to eager load other associations
scope :search_import, -> { includes(:address, :event_types, :pricing_details, :ratings) }
after_save :reindex if try(:address).present?
###### controller action ##########
#query = []
#query << params[:venue_name] if params[:venue_name].present?
#query << params[:address] if params[:address].present?
#query << params[:venue_capacity_in_persons] if params[:venue_capacity_in_persons].present?
#query << params[:food_type] if params[:food_type].present?
#query << params[:event_name] if params[:event_name].present?
#query = #query.flatten.compact
logger.tagged("SITE WIDE SEARCH"){ logger.info "**************SEARCH QUERY***#{#query}******************" }
##TODO-add constraints to handle range for capacity in persons
####halls = Hall.get_completed_halls_only.paginate(:page => params[:page]).search(#query).results
###halls = Hall.get_completed_halls_only.search(#query)
#halls = Hall.get_completed_halls_only.search params[:address],
where: {
capacity_in_persons: {lte: params[:venue_capacity_in_persons]},
food_type: params[:food_type],
event_type_name: params[:event_name]
}
I have added changes to my address.rb to find venue nearby and i think it working fine but any suggestions are welcome.address.rb is polymorphic and has address_1 attribute to store address coming from google dropdown along with geocoding from geocoder gem.
models/address.rb
###address belongs_to venue
searchkick locations: [:address_1]
## call Address.reindex if this method is changed
def search_data
attributes.except("id").merge(
address_1: {lat: latitude, lon: longitude},
city: city,
state: state,
zipcode: zipcode ##unless addressable_type == "Hall"
)
end
I have implemented ajax-datatables-rails for one table where I get raw records with query using group
class ListcontractorsDatatable < AjaxDatatablesRails::Base
def view_columns
# Declare strings in this format: ModelName.column_name
# or in aliased_join_table.column_name format
#view_columns ||= {
id: { source: "Contractor.id", cond: :eq },
name: { source: "Contractor.name" },
city: { source: "Contractor.city" },
ico: { source: "Contractor.ico" },
country: { source: "Contractor.country" },
count: {source: "Contract.count"}
}
end
def_delegators :#view, :link_to, :showcontractor_path, :content_tag
def data
records.map do |contractor|
{
# example:
id: contractor.id,
name: link_to(contractor.name, showcontractor_path(contractor.id)),
city: contractor.city,
ico: contractor.ico,
country: contractor.country,
count: contractor.count,
extlink: link_to(content_tag(:i,nil,class: 'fa fa-external-link'), 'https://www.somepage.com/'+contractor.ico.to_s)
}
end
end
private
def get_raw_records
Contractor.joins(:contracts).select("contractors.id,name,ico,city,country,count(resultinfo_id) as count")
.group("contractors.id,contractors.name,contractors.ico,contractors.city,contractors.country")
end
end
everything works (ordering, pagination, all columns are correct) except search. When I put anything into search I got error
PG::GroupingError: ERROR: aggregate functions are not allowed in
WHERE
I cannot find any working solution with group in query for branch 0.4.0. Could you please help me? thx
Query of searchkick get wrong result.
I have this one record in db:
2.2.0 :047 > Product.first
#<Product id: 1, title: "Ball", description: "<p>Ball</p>\r\n", price: 10, material: "lalala", created_at: "2015-04-21 04:30:53", updated_at: "2015-04-21 04:30:53", preview: "images__1_.jpg", count: 20>
in controller Product and action search i have this code:
def search
#products = Product.search "*", where:
{
count: 10..18
}
end
and after this, a get result, that the with this values, count is exist.
But in db count = 20. And all time, get wrong result. I don't know why?
I get not correct result, 'cause i don't have hash, in model and need reindex of Model.
In model:
def search_data
{
count: count,
price: price,
title: title,
category_id: categories.map($:id)
}
end
and after that, in rails console wrote:
Product.reindex