Reputation: 228
I have this search feature that has a text/keyword box and a bunch of filters; I have it implemented right now with the following structure:
query do
boolean do
must { string params[:text], default_operator: "AND" } unless params[:text].blank?
must { } unless
must { } unless
should { } unless
# some more must / should / must_not queries
end
end
# Some sorting
As far as I have read, it would be a better approach to implement it using the actual filter
provided by tire (in terms of speed and cacheing).
I want to ask what would be the right way of implementing this? I couldn't find a way of passing a similar boolean
block to a filter
... That would be nice. Maybe I am doing it wrong?
I am thinking of doing something like
# This would be the main query, by text/keyword
query { string params[:text], default_operator: "AND" } unless params[:text].blank?
filter do
boolean do
# My regular filters that I implemented with queries
must { } unless
must { } unless
should { } unless
end
end
# Some sorting
This gives me the following error (at the filter
block line):
ArgumentError - wrong number of arguments (0 for 1):
Also, I know that this behavior can be achieved using ElasticSearch JSON queries, as shown here: http://www.elasticsearch.org/guide/reference/query-dsl/bool-filter/ . So I assume tire provides a similar functionality on top of this feature.
Thank you for your help.
EDIT
What I am trying to do now is to use a filtered search, in the following way:
query do
filtered do
query { string params[:text], default_operator: "AND" } unless params[:text].blank?
# And here I would like to add the filter block... but for now I am using the filter :and
filter :and, { :terms => { } } unless params[:something1].blank?,
{ :terms => { } } unless params[:something2].blank?,
{ :range => { } } unless params[:something3].blank?,
# more filters that need the AND behavior
filter :or, { :terms => { } } unless params[:something4].blank?
# more filters that need the OR behavior
end
end
I am thinking of this approach because I also read that a filter :and
is faster than a boolean
one. Is this correct?
Now, will these filters still get cached? Also, is this the right approach in this situation?
Thank you!
EDIT
From what I've read in the issue posted in the comments, I think I could do something like:
filter :bool => [
{ :must => { :terms => { } } } unless ... ,
{ :must => { :terms => { } } } unless ... ,
{ :should => { :terms => { } } } unless ... ,
# and the other filters
]
Is this right?
Thanks!
Upvotes: 1
Views: 2434
Reputation: 228
I just found the following issue https://github.com/karmi/tire/issues/2 . Seems like karmi did not really implement this feature for filter?
Meanwhile, as I saw in some of the integration tests, I think I can do something like this:
filter :bool => [
{ :must => { :terms => { } } } unless ... ,
{ :must => { :terms => { } } } unless ... ,
{ :should => { :terms => { } } } unless ... ,
# and the other filters
]
Here is the source: https://github.com/karmi/tire/commit/01ba026
Also, I ended up writing simple, single filters for my particular case:
query { all } unless !params[:keyword].blank?
query { string params[:keyword], default_operator: "AND" } unless params[:keyword].blank?
filter :term, :a => params[:a] unless params[:a].blank?
filter :term, :b => params[:b] unless params[:b].blank?
filter :range, :c => { gte: params[:c_min] } unless params[:c_min].blank?
filter :range, :c => { lte: params[:c_max] } unless params[:c_max].blank?
filter :terms, :d => params[:d] unless params[:d].blank?
# and more such filters, just wanted to give more examples since
# the documentation is so sparse over the internet and I know what
# it takes to find everything in one place :)
I still think this is not the most convenient approach but it does the job in my case (a boolean block would be nice to have, for filter, but as far as I've read, an :and
filter is faster than a :bool
one - and listing a bunch of filters, as I did above, as far as I understood so far, creates such an :and
filter).
I think this is a better approach than the initial one, of having only queries, since now these filters could be cached (as far as I read, again).
Hope this would help someone in the future :)
Also, if anyone has a better suggestion / explanation / helpful tip, please feel free to contribute!
Thanks!
Upvotes: 4