Ruby on Rails/Mongo筛选仅存在于filtered_apps数组的记录问题排查
代码逻辑问题诊断
你的对比逻辑无法正常运行,是由4个明确的错误导致的:
- 变量未初始化:代码中直接对
previous_apps_array、@non_dupe_apps执行<<追加操作,但这两个变量从未被定义初始化,运行时会直接抛出undefined method '<<' for nil:NilClass错误。 - 分支逻辑与打印文案完全颠倒:
if app.family_id.in?(previous_apps_array) == false对应的是「当前记录的family_id不存在于previous_apps中,属于filtered_apps独有记录」的场景,else分支对应的是「family_id同时存在于两个数组中,属于共有重复记录」的场景,但你在else分支打印的是No duplicate found for application #{app.hbx_id},和实际逻辑完全相反。 - 语法错误:对比循环段多写了一个多余的
end闭合标记,Ruby解析代码时会直接抛出语法错误,无法正常运行。 - 冗余遍历性能差:手动遍历previous_apps全量记录、逐行提取family_id存入数组的写法会把所有匹配的Application记录全量加载到内存实例化,数据量稍大时运行效率极低。
最简修正实现
不需要手写逐行判断循环,直接用Ruby内置的集合方法+ORM的字段提取能力,几行代码就能完成需求,同时避免上述错误:
start_date = Date.parse("2022-02-05") end_date = Date.parse("2022-05-17") valid_year = start_date.year # 查询符合筛选条件的目标申请记录 filtered_apps = FinancialAssistance::Application.where( :is_requesting_info_in_mail => true, :aasm_state => "determined", :submitted_at => { "$exists" => true, "$gte" => start_date, "$lte" => end_date } ).to_a # 直接用pluck提取比对用的family_id数组,不需要手动遍历,不会实例化全量记录 previous_family_ids = FinancialAssistance::Application.where( is_requesting_info_in_mail: true, :submitted_at => { "$exists" => true, "$gte" => valid_year } ).pluck(:family_id) # 分组:过滤出filtered_apps独有的记录存入新数组,剩余的就是两数组共有的记录 non_dupe_apps = filtered_apps.reject { |app| previous_family_ids.include?(app.family_id) } dupe_apps = filtered_apps - non_dupe_apps # 打印两数组共有的记录 dupe_apps.each do |app| puts "存在共有重复记录,申请HBX ID为:#{app.hbx_id}" end # 后续直接调用non_dupe_apps数组处理CSV导出逻辑即可
如果数据量较大,还可以直接在数据库层完成过滤,完全不需要把全量记录加载到内存,运行效率更高:
# 直接查询出filtered_apps中独有的记录,所有过滤逻辑在MongoDB侧完成 non_dupe_apps = FinancialAssistance::Application.where( :is_requesting_info_in_mail => true, :aasm_state => "determined", :submitted_at => { "$exists" => true, "$gte" => start_date, "$lte" => end_date }, :family_id.nin => FinancialAssistance::Application.where( is_requesting_info_in_mail: true, :submitted_at => { "$exists" => true, "$gte" => valid_year } ).pluck(:family_id) )
内容的提问来源于stack exchange,提问作者beervenger
相关产品推荐
相关产品推荐

