All threads / Searchkick Aggregations - Need to show Users only from Current.account

Ask A Question

Notifications

You’re not receiving notifications from this thread.

Searchkick Aggregations - Need to show Users only from Current.account

Bruno Steinmann asked in Rails

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?

Have you double checked to make sure you're indexing the account_id in ElasticSearch?

wow - great! i had a little typo there. now it works perfectly. thanks a lot for super fast help - cheers.

Awesome! I like when solutions are that easy. 🤘

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 33,399+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.