Ruby - 用于链式ActiveRecord查询的较便宜的方式

时间:2015-07-15 21:29:02

标签: ruby-on-rails ruby activerecord

我目前的工作是什么,但似乎非常昂贵,任何降低成本的想法都会很棒!

User有许多Plans,其中有PlanDatesPlanDates。每个recipe_id都有一个由Plan属性表示的配方。每个meal_type都有一个Meat属性,该属性为VegetarianChoiceRecipe,后者表示混合。每个type_of_meal都有一个Meat属性VegetarianRecipe。每个name也有一个友好的options_for_select属性。

对于给定的PlanDate,我需要使用以下格式构建[ [recipe_id, "recipe_name"], [recipe_id, "recipe_name"] ... ]

recipe_ids

选项:

  • 必须删除之前已提供给用户的所有recipe_ids(无论计划如何)
  • 必须删除所有类型不匹配的Meat(例如,如果计划指定了Vegetarian,则选项不得包含任何recipe_ids Choice),当然这如果计划已# builds an array of all the recipe_ids that have been given to this User on some PlanDate on some Plan recipes_used_before_for_this_user = PlanDate.select { |pd| pd.plan.user.id == user_id }.map { |pd| pd.recipe_id } # narrows down the world of recipes to those that do NOT have an id of a recipe_used_before_for_this_user recipes_not_used_before = Recipe.select { |r| (recipes_used_before_for_this_user.include? r.id) == false } # going forward, let's assume current_pd = the PlanDate object in question if current_pd.plan.meal_type == "Choice" # easiest: if the meal_type is "Choice" then we just take the recipes_not_used_before and map them into the appropriate format recipe_choices_array = recipes_not_used_before.map { |r| [ r.id, r.name ] } else # if the plan has a "Meat" or "Vegetarian" specification, we need to first narrow the recipes_not_used_before down by the right type and then map into the appropriate format recipe_choices_array = recipes_not_used_before.select { |r| r.type_of_meal == potential_pd.first.plan.meal_type }.map { |r| [ r.id, r.name ] } end 指定
  • ,则不属实

这是我目前拥有的代码:

// Remove user
$scope.removeRecord = function(userId) {
    var userUrl = fbURL + user_table + '/' + userId;
    $scope.user = $firebase(new Firebase(userUrl));
    $scope.user.$remove()
    $scope.alerts.splice(0, 1);
    $scope.alerts.push({
        type: 'success',
        msg: "User removed successfully!"
    });
};

再次,工作,但我有很多PlanDates和很多食谱,所以如果有任何方法可以进一步简化,那就会喜欢你的想法。谢谢!

1 个答案:

答案 0 :(得分:0)

您遇到昂贵查询的原因是因为您实际上并未使用ActiveRecord的查询接口,甚至SQL来缩小查询范围,而是将整个数据集加载到Ruby内存对象中,然后在Ruby中循环结果。

我怀疑如果你检查你的日志文件,你会看到这样的东西:

>> PlanDate.select{ |pd| pd.plan.user.id == user_id }.map { |pd| pd.recipe_id }
  PlanDate Load (1.3ms)  SELECT "plan_dates".* FROM "plan_dates"
=> [#<PlanDate....

您要做的是使用ActiveRecord的查询接口来构建查询,如下所示:

PlanDate.includes(plan: [:user]).where("plan.user_id == ?", :user_id).pluck('recipe_id')

首先做的是:Specify relationships to be included in the result set,然后是specify the where conditions的SQL查询,最后使用pluck提取配方ID。

有关详细信息,请参阅http://guides.rubyonrails.org/active_record_querying.html