Rails 5.1中如何用pg_search显示搜索结果总计数?
Hey there! Let's figure out how to get that total count you need. It sounds like right now you're showing how many variations each individual product has, but you want a top-level total of either all matching variations or all variations across your search results. Let's break this down into two common scenarios, depending on what exactly you're aiming for:
Scenario 1: Total count of only variations that match your search query
This is probably what you want if your search targets variation attributes (like SKU, size, or custom fields) and you want to show how many specific variations hit the mark.
Step 1: Add a pg_search scope to your Variation model
Instead of only searching from the Product side, define a scope on Variation that includes product attributes if you need them (skip the associated_against part if you don't search product fields):
# app/models/variation.rb class Variation < ApplicationRecord belongs_to :product include PgSearch::Model pg_search_scope :search_including_product, associated_against: { product: [:name, :description] # Include product fields if you search them }, against: [:name, :sku, :price], # Your variation-specific search fields using: { tsearch: { prefix: true } # Keep your existing pg_search settings } end
Step 2: Update your controller to fetch variations and calculate the total
In your products_controller.rb, adjust the index action to pull matching variations, group them by product, and get the total count:
# app/controllers/products_controller.rb def index if params[:query].present? # Fetch matching variations with their product data to avoid N+1 queries @matching_variations = Variation.search_including_product(params[:query]).includes(:product) @total_variations_count = @matching_variations.count # Group variations by product for clean display @products_with_matches = @matching_variations.group_by(&:product) else # Default state: show all products and their variations @products = Product.all.includes(:variations) @total_variations_count = @products.joins(:variations).count end end
Step 3: Update your view to show the total and grouped results
In products/index.html.erb, add the total count at the top, then loop through the grouped products:
<h1>Product Search Results</h1> <% if params[:query].present? %> <p class="total-count">Found <%= @total_variations_count %> matching variations across <%= @products_with_matches.count %> products</p> <% @products_with_matches.each do |product, variations| %> <div class="product-card"> <h3><%= product.name %></h3> <p>This product has <%= variations.count %> matching variations:</p> <ul> <% variations.each do |variation| %> <li><%= variation.name %> (SKU: <%= variation.sku %>)</li> <% end %> </ul> </div> <% end %> <% else %> <!-- Your default all-products display here --> <p>Showing all <%= @products.count %> products with <%= @total_variations_count %> total variations</p> <% @products.each do |product| %> <!-- Product and its variations --> <% end %> <% end %>
Scenario 2: Total count of all variations from products that matched your search
If you just want to show how many variations exist across all products that came up in your search (even if some variations don't match the query), this is simpler:
Update your controller
# app/controllers/products_controller.rb def index if params[:query].present? @products = Product.your_existing_search_scope(params[:query]).includes(:variations) # Calculate total variations across all matching products (single SQL query) @total_variations_count = @products.joins(:variations).count else @products = Product.all.includes(:variations) @total_variations_count = @products.joins(:variations).count end end
Update your view
Add the total count at the top, then keep your existing product display:
<p>Found <%= @products.count %> products with <%= @total_variations_count %> total variations</p> <% @products.each do |product| %> <div class="product-card"> <h3><%= product.name %></h3> <p>Variations: <%= product.variations.count %></p> <!-- Your variation list here --> </div> <% end %>
Pro Tip for Performance
Avoid using @products.sum(&:variations_count) because that triggers an N+1 query (one count per product). Using @products.joins(:variations).count runs as a single SQL query and is way faster, especially with large datasets.
内容的提问来源于stack exchange,提问作者Charles Smith

