search_cop icon indicating copy to clipboard operation
search_cop copied to clipboard

multiple where conditions and concatenated with AND

Open danieldias51 opened this issue 5 years ago • 3 comments

Hi,

I'm using search_cop to perform a full text search on two models with a relationship, but the way WHERE condition is generated is not allowing me to get any results.

The scenario: I've a model lets call it A and it has a one to many relation with a model B. This model B is a table with synonyms, so it just has a "synonym" and the foreign key for the model A.

I've created on the model A a grouped FTS key attributes all: [:name, :description, ...] and on the model B I've just one field with FTS key.

My problem, the query generated has 2 "MATCH AGAINST" conditions, one for the first grouped key and one for the other key, exactly as it should, but they are concatenated by an AND then:

WHERE 
((MATCH(`A`.`name`, `A`.`description`, `A`.etc...) AGAINST('+my +search' IN BOOLEAN MODE))) 
AND 
((MATCH(`B`.`name`) AGAINST('+my +search' IN BOOLEAN MODE)))

Since the second table is a synonym table, if it doesn't match the search it prevents me from getting results...

Is there a way to use OR instead of an AND to concatenate the conditions? If not, I'd be glad to contribute if you want.

I'm facing also other issue, the + added before each term. This make the term required, so if the user type a word without a match, the hole query doesn't return results. Is there an option to prevent to add the +?

I'd be glad to create a PR to add those features if you want. I would only need some tips from you.

danieldias51 avatar Jul 15 '19 15:07 danieldias51

Hi, thx for your feedback.

So, in essence you ask for what elasticsearch calls the "default_operator": https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html

Currently, search_cop always uses AND as default operator, such that if you search for "term1 term2", search_cop interpretes it as "term1 AND term2", but you want it to interprete it as "term1 OR term2" by default. It should be possible to add this feature and i'm open for a PR.

Your second point should be "fixed" via the default_operator option as well.

mrkamel avatar Jul 15 '19 15:07 mrkamel

So any tips where I should start looking? Can you give me a little brief where and how this interpretation is being handled?

danieldias51 avatar Jul 15 '19 16:07 danieldias51

Sure, it starts in the treetop grammer. More specifically, in rule and_expression spaces are interpreted as AND operators. We need to change <AndExpression> within

... / space !('OR' / 'or')) complex_expression <AndExpression> / ...

to

<AndOrExpression> and add

class AndOrExpression
  def evaluate
     [elements.first.evaluate, elements.last.evaluate].inject(query_info....default_operator)
  end
end

in search_cop_grammer.rb, while the default_operator needs to be passed through via the query_info object.

mrkamel avatar Jul 15 '19 18:07 mrkamel