pg_search icon indicating copy to clipboard operation
pg_search copied to clipboard

Override default order_within_rank in pg_search_scope to assist dynamic ordering

Open NeoElit opened this issue 8 years ago • 2 comments

Is there a proper way to suppress the default order_within_rank inside pg_search_scope? In my use case this (order_within_rank) should be varying based on the context.

Currently I have a two options:

  1. Use different pg_search_scopes (lots of scopes.. side effects?)
  2. set order_within_rank => "1 DESC" (side effects?)

NeoElit avatar Mar 28 '17 07:03 NeoElit

Would be great to have an proper way. In the meantime I propose a third workaround:

with_pg_search_rank.reorder('pg_search_rank DESC').order(new_sort)

It will override the order using the rank as first ordering criteria and new_sort as second ordering criteria. Basically is just like order_within_rank, but ordering attribute can be changed in runtime. This solution has no performance hit.

micred avatar Oct 22 '20 11:10 micred

@micred This is working quite nicely when you're not merging results between multiple models.

I'm curious, do you know how to handle this when you have this type of set up?

When I join and merge 2 models and at least 1 search term is returned I get this error missing attribute 'user_id' for LoginActivity. If I comment out your changes then no error occurs but the User model results aren't sorted correctly, however the LoginActivity results are sorted correctly. Here's the set up:

# User model (has_many login_activities)

    def self.search_and_sort(query, column, direction)
      if query.present?
        pg_search(query)
          .with_pg_search_rank.reorder("pg_search_rank DESC")
          .sort_by_params(column, direction)
      else
        all.sort_by_params(column, direction)
      end
    end
# LoginActivity model (has_one user)

    def search_and_sort(query, column, direction)
      queryable =
        if query.present?
            joins(:user).merge(User.search_and_sort(column, sort, direction))
        else
          all
        end.sort_by_params(column, direction)
    end

sort_by_params in this case is a function that ultimately calls order(column, direction).

I get the error when I call this from my login_activities_controller.rb:

LoginActivity.search_and_sort("Hello", "identity", "desc")

If I inspect the result of what's coming back, I end up with a list of LoginActivity models but they all have the contents / fields of the User model. When there's no search term or a search term with zero results then they correctly have the fields of the LoginActivity model. Not really sure where to go from here.

I can code around this by skipping the .reorder when searching into the User model from LoginActivity but figured there might be a cleaner way.

nickjj avatar Oct 23 '23 21:10 nickjj