I have 15,000 courses and I would like to boost the title of each class so exact matches of a class are boosted above everything else.
When I do Course.seach_kick('theory of interest' , 1)
The correct search is returned with the course 'theory of interest' as the first result.
However, when I do Course.search_kick('theory of interest 3618', 1)
3618 being the catalog_number, no results are returned. I expected the theory of interest course to be returned, and returned first. It seems the search is looking for the complete string 'theory of interest 3618' be included in the title of the course.
I understand 'and' is the default operator, Is it a requirement that I have to use the 'or' operator? I am hesitant to use the 'or' operator because of the unexpected results.
Thanks, I really enjoy using the gem.
search method:
def self.search_kick(query, page)
search(query,
fields: ["title^10", "description", "crse_id", "subject", "catalog_number" ],
facets: [:subject],
misspellings: false,
page: page,
per_page: 20
)
end
def search_data
{
title: title,
description: description,
crse_id: crse_id,
subject: subject,
catalog_number: catalog_nbr
}
end
Why not filter catalog_number in where clause:
search(query,
fields: ["title^10", "description", "crse_id", "subject" ],
facets: [:subject],
misspellings: false,
where: {catalog_number: 3618},
page: page,
per_page: 20
)
In most cases, where clause comes from an IF:
conditions = {}
if params[:catalog_number].present?
conditions[:catalog_number] = params[:catalog_number].to_i
end
search(query,
fields: ["title^10", "description", "crse_id", "subject" ],
facets: [:subject],
misspellings: false,
where: conditions,
page: page,
per_page: 20
)
You can insert as many as possible filters into where clause, just the same as ActiveRecord.where()
docs ref: https://github.com/ankane/searchkick#queries
Related
I use the following code to search using SearchKick:
Book.search(q,
misspellings: { below: 5 },
fields: [:name, :author, :pages],
order: { name: 'asc' },
page: params[:page],
per_page: 20)
When I search name and author it works fine.
However, when I search 130 for page it doesn't search the field.
name and author are string fields of a Book model, and page is an integer field.
My guess is the 130 is coming through as a string, and it is incorrectly trying to match the integer.
How can I make it so that I can search based on page numbers?
Have you tried calling to_i on params[:page]?
Book.search(q,
misspellings: { below: 5 },
fields: [:name, :author, :pages],
order: { name: 'asc' },
page: params[:page]&.to_i,
per_page: 20)
If you're right and it is comparing integer to string, this would fix it.
How to make searchkick search integer fields?
Let's say i have a Book model with three properties namely name:string, author:string and pages:integer.
I want to search according to pages field. Right now if i use a query like below it works for string fields i.e name and author but it doesnt work for pages field which is of integer type.
Book.search(q,
misspellings: { below: 5 },
fields: [:name, :author, :pages],
order: { name: 'asc' },
page: params[:page],
per_page: 20)
I go to console and just searched Book.search(120, fields: [:pages]) and it returns empty result even though there are records with pages 120. Why is searchkick not searching for integer fields? I appreciate any help to this dilemma i am facing. Thanks!
I fixed it with this
In Book model
def search_data
{
name: name,
author: author,
pages: pages.to_s
}
end
I am indexing some of my data with searchkick (https://github.com/ankane/searchkick) as an array and it works almost fine :)
def search_data
{isbn: isbn,
title: title,
abstract_long: abstract_long,
authors: authors.map(&:name)}
end
The field I'm interested in is authors.
What I'd like to accomplish is to search for "Marias" and find all the authors that actually have that exact string in their surname like (Javier Marias) and not all the Maria/Mario/Marais that Searchkick returns, and have them with a much bigger priority.
This is how I search right now
Book.search(#search_key,
fields: [:authors, :title, {isbn: :exact}],
boost_by: {authors: 10, title: 5, isbn: 1})
Is this possible at all? TIA
In Elasticsearch it has a regular match to deal with this case, but abandoned by Searchkick.
You could choose a walk around way for this case:
def search_data
{
isbn: isbn,
title: title,
abstract_long: abstract_long,
author_ids: authors.map(&:id)
}
end
For search:
author_ids = Author.where(surname: 'Marias').map(&:id)
Book.search(
#search_key,
where: {author_ids: {in: author_ids}},
fields: [:title, {isbn: :exact}],
boost_by: {title: 5, isbn: 1}
)
Using the elastsearch-rails gem, currently I have:
response = Employee.search(
size: 20,
query: {
multi_match: {
"query" => search_terms,
"type" => "cross_fields",
"fields" => ["first_name^3", "last_name^3", "full_name^4", "email", "job_description^5", "job_title^5"]
}
}
)
What I notice is that by doing the multi-match / cross_fields search, if I search for a term that appears only once in an Employee database column (e.g., "John" would only appear in first_name, not job_description or job_title), then I get no results back. If a term, (say a job title like "lawyer" appears in more than 1 field such as job_description and job_title), I get results back. Why is this? This seems counter-intuitive.
Using Elasticsearch with Rails 3 and tire gem.
I have got facets to work on a couple of fields, but I now have a special requirement and not sure it is possible.
I have two fields on my model Project that both store the same values: Country1 and Country2
The user is allowed to store up to two countries for a project. The drop down menus on both are the same. Neither field is required.
What I would like is a single facet that 'merges' the values from Country1 and Country2 and would handle clicking on those facets intelligently (i.e. would find it whether it was in 1 or 2)
Here's my model so far: (note Country1/2 can be multiple words)
class Project < ActiveRecord::Base
mapping do
indexes :id
indexes :title, :boost => 100
indexes :subtitle
indexes :country1, :type => 'string', :index => 'not_analyzed'
indexes :country2, :type => 'string', :index => 'not_analyzed'
end
def self.search(params)
tire.search(load: true, page: params[:page], per_page: 10) do
query do
boolean do
must { string params[:query], default_operator: "AND" } if params[:query].present?
must { term :country1, params[:country] } if params[:country].present?
end
end
sort { by :display_type, "desc" }
facet "country" do
terms :country1
end
end
end
Any tips greatly appreciated!
This commit https://github.com/karmi/tire/commit/730813f in Tire brings support for aggregating over multiple fields in the "terms" facet.
The interface is:
Tire.search('articles-test') do
query { string 'foo' }
# Pass fields as an array, not string
facet('multi') { terms ['bar', 'baz'] }
end
according to the elasticsearch docs for the terms facet http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html this should be possible:
Multi Fields:
The term facet can be executed against more than one field, returning
the aggregation result across those fields. For example:
{
"query" : {
"match_all" : { }
},
"facets" : {
"tag" : {
"terms" : {
"fields" : ["tag1", "tag2"],
"size" : 10
}
}
}
}
did you try providing an array of fields to the term facet like terms :country1, :country2 ?
This seems to work but I need to test it more: facet('country') { terms fields: [:country1, :country2]}