Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disjunctions and Conjunctions are not working with inner join #1000

Open
sunloverz opened this issue Mar 12, 2021 · 9 comments
Open

Disjunctions and Conjunctions are not working with inner join #1000

sunloverz opened this issue Mar 12, 2021 · 9 comments
Assignees
Labels

Comments

@sunloverz
Copy link

I have the following models:

class Book
  has_many :authors  

  searchable do
    join(:job_id, :target => Author, :type => :integer, :join => { :from => :book_id, :to => :id })
    join(:score, :target => Author, :type => :double, :join => { :from => :book_id, :to => :id })
  end
end

class Author 
  belongs_to :book

  searchable do
    integer :book_id
    integer :job_id
    double :score
  end
end

But conjunction here is not working with join fields

Book.search do
  all_of do 
    with(:score).greater_than(10.0)
    with(:job_id, job_id)
  end
end
@mlh758
Copy link
Collaborator

mlh758 commented Mar 12, 2021

@gr8bit this looks topical to you.

@gr8bit
Copy link

gr8bit commented Mar 12, 2021

@mlh758 wtf, that's exactly what we were talking about yesterday. :O What a coincidence...

@sunloverz unfortunate news: I don't think this currently works. mlh785 and myself have been discussing this in #885 since yesterday because I had the same issue. The joins aren't merged. You'll find a hint on adjust_solr_params method you can use in your search to manipulate the solr query for now. I'll share my code when I'm done (should be later today).

@mlh758 mlh758 added the bug label Mar 12, 2021
@mlh758
Copy link
Collaborator

mlh758 commented Mar 12, 2021

We should use this issue to continue the discussion since #885 was for something else originally and this is exactly on topic. I think this should be solvable but I haven't had time to look yet. I'd certainly advocate using adjust_solr_params in the mean time.

@mlh758 mlh758 self-assigned this Mar 12, 2021
@sunloverz
Copy link
Author

@gr8bit If you have a code could you please share it? I would appreciate greatly.

@gr8bit
Copy link

gr8bit commented Mar 15, 2021

@sunloverz untested, will test tomorrow myself. ;) Seems to work fine for me... Written on/for Ruby 2.6+ and (probably, I didn't check the array methods) Rails.

    Book.search do
      adjust_solr_params do |params|
        new_fq = []
        params[:fq]
          .group_by { |field_query|
            # adapt this join query regexp to match only the joins you want to
            # merge or all compatible joins will be merged (default)
            field_query[/\A{!join from=.+? to=.+? v='type:".+?" AND /]
          }
          .each { |base_join, field_queries|
            # add non-matching field queries (key nil) and single occurrences
            # to new field queries directly
            new_fq.concat(field_queries) && next if !base_join || field_queries.length == 1
            # merge matched multiple join queries
            # 1. extract conditions from joins and combine into a single query
            conditions =
              field_queries.map { |join_query|
                cond = join_query[base_join.length..][/.*?(?=(?<!\\)')/]
                "( #{cond} )"
              }.join(" AND ")
            # 2. as the base_join is only a part of the join, add all
            # conditions to the first join, replacing its previous
            # condition.
            new_fq << base_join + field_queries.first[base_join.length..].sub(/\A.*?(?=(?<!\\)')/, conditions)
          }
        params[:fq] = new_fq
      end
      all_of do 
        with(:score).greater_than(10.0)
        with(:job_id, job_id)
      end
    end

@sunloverz
Copy link
Author

sunloverz commented Mar 15, 2021

@gr8bit Thank you very much for your code and explanation!

It generates the following sunspot request without AND keyword.
<Sunspot::Search:{:fq=>["type:Book", "{!join from=book_id_i to=id_i}score_e:{10\\.0 TO *}", "{!join from=book_id_i to=id_i}job_id_i:859"], :start=>0, :rows=>30, :q=>"*:*"}>

I guess it should generate a query like that? ({!join from=book_id_i to=id_i}job_id_i:859 AND {!join from=book_id_i to=id_i}score_e:{25\\.0 TO *})

@sunloverz
Copy link
Author

I have decided to use the following code as a temporary solution. Thanks, guys!

   Book.search do
      adjust_solr_params do |params|
        params[:fq] = "{!join from=book_id_i to=id_i}job_id_i:859 AND score_e:{10.0 TO *}"
      end
    end

@gr8bit
Copy link

gr8bit commented Mar 15, 2021

Hi @sunloverz, doesn't your query miss the type of the entries to join? Like type:"Author"? I think this query <Sunspot::Search:{:fq=>["type:Book", "{!join from=book_id_i to=id_i}score_e:{10\\.0 TO *}", "{!join from=book_id_i to=id_i}job_id_i:859"], :start=>0, :rows=>30, :q=>"*:*"}> might give you wrong results and currently only works because Author is the only entity in Solr that has a book_id...

Unfortunately my join queries look different and have a v "attribute" instead of a value after the join. wtf..?

Regarding your current workaround, it removes the type query - perhaps this might produce the results you want?

Book.search do
  adjust_solr_params do |params|
    params[:fq] = [params[:fq].first, "{!join from=book_id_i to=id_i}type:\"Author\" AND job_id_i:859 AND score_e:{10.0 TO *}"]
  end
end

@sunloverz
Copy link
Author

Hi @gr8bit, I don't know why it behaves differently. I'm using the latest sunspot 2.5.0 version.

Thanks for the suggestion, it works great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants