简体   繁体   中英

Rails - what is the most efficient way to build query for multiple tags

I have this situation:

Two models: - Meal - Tag

With a many-to-many relationship, So product can have assigned many tags.

There is additional table for association ( meal_id , tag_id ) Then user choose some tags (for example 8).

I must write query in Rails (but can be only sql idea), which return:

  1. meals which has assigned at least one tag from chosen by user.
  2. meals which has assigned all chosen tags.

I don't know how to do it in most efficient way. Could you help me a little?

Meal.rb

class Meal < ActiveRecord::Base
   has_and_belongs_to_many :tags
end

Tag.rb

class Tag < ActiveRecord::Base
   has_and_belongs_to_many :meals
end

Let's try to get Meal with dynamic tag_ids . You have to collect tag_ids then you join Meal by tag_ids

tag_ids = [1, 2, 3, 4]
Meal.joins(:tags).where('tags.id IN (?)', tags_ids).group("meals.id")
                    .having("COUNT(meals.id) >= ?", tag_ids.length)

I hope this help you.

To return the queries you want try the following:

  1. "Meals which has assigned at least one tag" :
    # we will store meal objects in this array
    #the ones that has at least one tag
    meals = []

    # go over all meals
    Meal.all.each do |meal|

      # if meal has tags store it
      if !meal.tags.blank?
        meals << meal
      end

    end

    # then I have all meals with at least one tag in my array called meals
    # and I can do whatever I want with it
    meals.each do |m|
      #do something with each meal
    end

    how_many_meals_with_one_tag_at_least = meals.count 
  1. "Meals which has assigned all chosen tags" . I think you mean: "Meals which has assigned all existent tags".
    # again our array to store meals
    meals = []

    maximumTags = Tag.all.count   

    Meal.all.each do |meal|

      if meal.tags.count == maximumTags
        meals << meal
      end

    end

    meals.each do |m|
      #do something with your meal with all tags assigned
    end

I know this is approach is more ruby than sql, but it's easy to implement and gets you there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM