Searchkick Aggregations - Need to show Users only from Current.account
My App uses Current.account from ActiveSupport and i need to show only Users (for filtering) who belongs to the Current.account.
The following Setup for Search Filters with Aggregations (searchkick) works so far. BUT:
- it does show all User Records - not only Current.account.users
- when i delete || "*" from the query in the controller i get nothing shown up
Means, i have a serious problem with this kind of "Top Level Scope".
# user.rb
  searchkick filterable: [:first_name, :languages, :account]
  has_many :user_languages
  has_many :languages, through: :user_languages
  belongs_to :account
    scope :search_import, -> { includes(:account, :languages) }
    def search_data
        {
            account_id: Current.account,
            first_name: first_name,
            languages: languages.map(&:name)
        }
    end
# user_controller.rb
def index
    query = params[User.where(account_id: Current.account)]  || "*" 
    args = {}
    args[:first_name] = params[:first_name] if params[:first_name].present?
    args[:languages] = params[:languages] if params[:languages].present?
    @users = User.search query, where: args,
                                aggs: {
                                  first_name: {},
                                  languages: {}
                               }
end
# users/index.html.erb
<div class="container">
  <div class="row">
    <div class="col-sm-3">
      <div><%= link_to "List All", users_path %></div><br>
      <h6>First Name</h6>
      <% @users.aggs["first_name"]["buckets"].each do |bucket| %>
        <div>
          <% if params[:first_name] == bucket["key"].to_s %>
            <strong><%= link_to bucket["key"], request.params.except(:first_name) %></strong>
          <% else %>
            <%= link_to bucket["key"], request.params.merge(first_name: bucket["key"]) %>
          <% end %>
          (<%= bucket["doc_count"] %>)
        </div>
      <% end %>
      <br>
      <h6>Languages</h6>
      <% @users.aggs["languages"]["buckets"].each do |bucket| %>
        <div>
          <% if params[:languages] == bucket["key"].to_s %>
            <strong><%= link_to bucket["key"], request.params.except(:languages) %></strong>
          <% else %>
            <%= link_to bucket["key"], request.params.merge(languages: bucket["key"]) %>
          <% end %>
          (<%= bucket["doc_count"] %>)
        </div>
      <% end %>
    </div>
    <div class="col-sm-9">
      <%= render 'user_index' %>
    </div>
  </div>
</div>
Thanks a lot for a any clue or hint - Cheers.
Bruno,
Make sure you add the account_id in your search's where so it filters down. ElasticSearch is going to keep a separate indexed copy of your database, so when you search it, you need to apply the same types of filters as you would in your db queries.
@Chris, thanks for fast reply. I am working quite some time on this piece of code - and whatever i try, it does not work. Or in other words: i don't know how to follow your advise and put the stuff together. Some more help is needed, i guess.
I think you just want something like:
def index
    query = params[User.where(account_id: Current.account)]  || "*" 
    args = {}
        args[:account_id] = Current.account.id
    args[:first_name] = params[:first_name] if params[:first_name].present?
    args[:languages] = params[:languages] if params[:languages].present?
    @users = User.search query, where: args,
                                aggs: {
                                  first_name: {},
                                  languages: {}
                               }
end
Thanks mate. I have tried a lot and have been at this point before - but it does not show anything on the index page. I want to show you some server-logs:
using code from above:
User Search (9.8ms)  users_development/_search {"aggs":{"first_name":{"filter":{"bool":{"must":[{"term":{"account_id":1}}]}},"aggs":{"first_name":{"terms":{"field":"first_name","size":1000}}}},"languages":{"filter":{"bool":{"must":[{"term":{"account_id":1}}]}},"aggs":{"languages":{"terms":{"field":"languages","size":1000}}}}},"query":{"bool":{"must":{"match_all":{}},"filter":[{"term":{"account_id":1}}]}},"timeout":"11s","_source":false,"size":10000}
this looks fine for account: :{"must":[{"term":{"account_id":1}}]} => exactly what i need, but no User Load and empty view.
Code without query:
User Search (5.0ms)  users_development/_search {"aggs":{"first_name":{"filter":{"bool":{"must":[{"term":{"account_id":1}}]}},"aggs":{"first_name":{"terms":{"field":"first_name","size":1000}}}},"languages":{"filter":{"bool":{"must":[{"term":{"account_id":1}}]}},"aggs":{"languages":{"terms":{"field":"languages","size":1000}}}}},"query":{"bool":{"must":{"match_all":{}},"filter":[{"term":{"account_id":1}}]}},"timeout":"11s","_source":false,"size":10000}
using query or not does the same thing, just in half of the time.
kicking out args[:account_id] = Current.account.id
User Search (4.7ms)  users_development/_search {"aggs":{"first_name":{"terms":{"field":"first_name","size":1000}},"languages":{"terms":{"field":"languages","size":1000}}},"query":{"match_all":{}},"timeout":"11s","_source":false,"size":10000}
 User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)  [["id", 1], ["id", 2], ["id", 3], ["id", 4], ["id", 5], ["id", 6], ["id", 7], ["id", 8], ["id", 9], ["id", 10]]
shows all of the users from all accounts - this is not what i need or want, but it shows, that the setup and view is pretty close to ok, only the scope for Current.account does not filter out the users..
Reindex shows:
User.reindex
  User Load (0.5ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1000]]
  Account Load (0.4ms)  SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" IN ($1, $2)  [["id", 1], ["id", 2]]
  Userlanguage Load (0.3ms)  SELECT "userlanguages".* FROM "userlanguages" WHERE "userlanguages"."user_id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)  [["user_id", 1], ["user_id", 2], ["user_id", 3], ["user_id", 4], ["user_id", 5], ["user_id", 6], ["user_id", 7], ["user_id", 8], ["user_id", 9], ["user_id", 10]]
  Language Load (0.3ms)  SELECT "languages".* FROM "languages" WHERE "languages"."id" IN ($1, $2)  [["id", 1], ["id", 2]]
  User Import (25.8ms)  {"count":10}
=> true
Here i am not sure, if correct - User Load does not list anything?
wow - great! i had a little typo there. now it works perfectly. thanks a lot for super fast help - cheers.

