如何对使用Parquet.Net读取Parquet文件得到的数组执行LINQ查询
问题根因
- 你当前
ReadParquetFile方法返回的是Parquet.Data.DataColumn类型的数组,属于按列存储的原始数据结构,每个数组元素对应Parquet文件中的一整列数据,并非你自定义的DataFrame行对象,LINQ查询中强制类型转换必然报错。 - 你原有的行组遍历逻辑存在缺陷:每次遍历行组都会给
allData重新赋值,最终只会保留最后一个行组的数据,前面行组的内容会全部丢失。 - 你的需求是按行做条件查询,必须先把列式存储的原始数据反序列化为每行对应的强类型实体,才能正常使用LINQ语法查询。
解决方法
方案1:使用Parquet.Net内置的强类型序列化(推荐)
不用手动处理列、行组逻辑,框架会自动完成列到行对象的映射:
- 首先定义和Parquet文件字段匹配的实体类(字段名需和Parquet字段名保持一致,类型匹配):
public class DataFrame { // 字段类型根据你实际Parquet文件的字段类型调整,大数值ID推荐用long public long EventId { get; set; } public double Loss { get; set; } // 其余字段按Parquet文件结构补全即可 }
- 改写读取方法,直接读取为强类型列表:
public static List<DataFrame> ReadParquetFile(string filePath) { using Stream fileStream = File.OpenRead(filePath); using var parquetReader = new Parquet.ParquetReader(fileStream); // 异步读取同步等待,也可改为异步方法 return parquetReader.ReadAsync<DataFrame>().GetAwaiter().GetResult().ToList(); }
- 改写Main方法的查询逻辑:
static void Main(string[] args) { var records = ReadParquetFile(@"F:\AutomationRunStation\11_12.parquet"); var queryResult = from data in records where data.EventId == 280000001 select data.Loss; // 遍历输出结果,直接输出queryResult只会打印集合类型名 foreach (var lossVal in queryResult) { Console.WriteLine(lossVal); } Console.ReadKey(); }
方案2:基于现有按列读取逻辑手动映射
如果你要保留现有按列读取的写法,可以手动把多列数据按索引拼接为行对象:
static void Main(string[] args) { var columns = ReadParquetFile(); // 取出对应列的原始数据数组 var eventIdArr = columns.First(c => c.Field.Name == "EventId").Data as long[]; var lossArr = columns.First(c => c.Field.Name == "Loss").Data as double[]; // 按索引拼接为DataFrame对象列表 var records = new List<DataFrame>(); for (int i = 0; i < eventIdArr.Length; i++) { records.Add(new DataFrame { EventId = eventIdArr[i], Loss = lossArr[i] }); } // 后续LINQ查询逻辑和方案1一致 var queryResult = from data in records where data.EventId == 280000001 select data.Loss; foreach (var lossVal in queryResult) { Console.WriteLine(lossVal); } Console.ReadKey(); }
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

