使用mysql2 gem查询MySQL数据,map方法未返回结果数组问题排查
嘿,我来帮你搞清楚这个疑惑~
首先,咱们得先明确mysql2 gem返回结果的特性:connect.query()返回的不是普通数组,而是一个Mysql2::Result对象——它是一个可枚举的结果集,但本身不是数组。不过正常来说,调用.map方法应该会遍历所有匹配的行,返回一个包含所有处理后元素的数组才对。那为什么你只得到一行结果?咱们一步步排查:
1. 先确认数据库里的真实数据
先别着急看代码,直接在MySQL客户端(比如命令行、Navicat、DataGrip)里跑你的查询语句:
SELECT * FROM data WHERE event_type = 'ALARM_OPENED' AND severity = '2'
看看返回的行数到底是多少。如果数据库里本来就只有一行符合条件,那.map返回的就是只有一个元素的数组,看起来像“一行”,但本质是数组里的单个元素——你可以用puts equipments.class验证下,它应该是Array类型。
2. 检查结果集的行数并转换为数组处理
如果数据库里确实有多行数据,那咱们先在代码里加一行,看看Mysql2::Result对象里到底有多少行:
result = connect.query("SELECT * FROM data WHERE event_type = 'ALARM_OPENED' AND severity = '2'") puts "结果集行数:#{result.size}" # 打印行数确认 equipments = result.map do |record| [ record['sourcetime'].strftime('%H:%M:%S'), record['equipment_id'], record['description'] # 补全你没写完的字段 ] end
如果result.size显示的行数大于1,但equipments还是只有一个元素,那大概率是Mysql2::Result的懒加载特性导致的小问题——咱们可以先把结果集转换成数组再处理:
result = connect.query("SELECT * FROM data WHERE event_type = 'ALARM_OPENED' AND severity = '2'").to_a equipments = result.map do |record| [ record['sourcetime'].strftime('%H:%M:%S'), record['equipment_id'], record['description'] ] end
to_a会把懒加载的结果集一次性转换成内存中的数组,之后再调用map就肯定会遍历所有元素了。
3. 排查代码中的其他操作
还有一种可能:你在调用map之前,有没有对result做过其他操作?比如调用了result.first、result.each或者result.next?这些方法会移动结果集的指针,如果指针已经到了末尾,后续的map就只能得到空或者剩余的少量行。如果有这种情况,记得把这些操作移到map之后,或者重新执行查询获取新的结果集。
内容的提问来源于stack exchange,提问作者Joshua Ng

