在 Apache Arrow 中按索引访问 Gadiva 过滤器结果
Access Gadiva filter result by index in Apache Arrow
也许我遗漏了一些明显的东西,但就我的生活而言,我无法弄清楚如何在 Gandiva 过滤器操作后访问数组的元素。
我已经链接了一个我这样编译的最小示例:
$ /usr/lib64/ccache/g++ -g -Wall -m64 -std=c++17 -pthread -fPIC \
-I/opt/data-an/include mwe.cc -o mwe \
-L/opt/data-an/lib64 -lgandiva -larrow
然后我 运行 像这样的二进制文件:
$ LD_LIBRARY_PATH=/opt/data-an/lib64 ./mwe
大体上这就是我正在尝试的(随后是 MWE 的摘录):
创建一个 5 元素向量:1, 3, 2, 4, 5
int num_records = 5;
arrow::Int64Builder i64builder;
ArrayPtr array0;
EXPECT_OK(i64builder.AppendValues({1, 3, 2, 4, 5}));
EXPECT_OK(i64builder.Finish(&array0));
使用Gandiva获取偶数元素,索引:2、3
// schema for input fields
auto field0 = field("f0", arrow::int64());
auto schema = arrow::schema({field0});
// even: f0 % 2 == 0
auto field0_node = TreeExprBuilder::MakeField(field0);
auto lit_2 = TreeExprBuilder::MakeLiteral(int64_t(2));
auto remainder = TreeExprBuilder::MakeFunction("mod", {field0_node, lit_2}, int64());
auto lit_0 = TreeExprBuilder::MakeLiteral(int64_t(0));
auto even = TreeExprBuilder::MakeFunction("equal", {remainder, lit_0}, boolean());
auto condition = TreeExprBuilder::MakeCondition(even);
// input record batch
auto in_batch = arrow::RecordBatch::Make(schema, num_records, {array0});
// filter
std::shared_ptr<Filter> filter;
EXPECT_OK(Filter::Make(schema, condition, &filter));
std::shared_ptr<SelectionVector> selected;
EXPECT_OK(SelectionVector::MakeInt16(num_records, pool_, &selected));
EXPECT_OK(filter->Evaluate(*in_batch, selected));
通过使用来自 Gandiva 过滤器的选择向量作为索引数组来访问原始数组中的偶数元素
// std::cout << "array0[0]: " << array0->Value(0); // doesn't compile
// error: ‘using element_type = class arrow::Array’ {aka ‘class
// arrow::Array’} has no member named ‘Value’
// downcast it to the correct derived class
auto array0_cast = std::dynamic_pointer_cast<NumericArray<Int64Type>>(array0);
std::cout << "array0[0]: " << array0_cast->Value(0) << std::endl;
但我似乎无法访问 selection vector 的元素。由于它被声明为 std::shared_ptr<arrow::Array>
,因此未找到 Value(..)
方法。因为我用 SelectionVector::MakeInt16(..)
填充了它,所以我尝试向下转换为 arrow::NumericArray<Int16Type>
,但是失败了!我不确定我哪里出错了。
auto idx_arr_cast = std::dynamic_pointer_cast<NumericArray<Int16Type>>(idx_arr);
if (idx_arr_cast) {
std::cout << "idx_arr[0]: " << idx_arr_cast->Value(0) << std::endl;
} else {
std::cerr << "idx_arr_cast is a nullptr!" << std::endl;
}
我还有一个相关但更笼统的问题。给定一个数组,如果我不知道确切的类型,我就找不到访问元素(或迭代它们)的方法。如果我知道类型,我可以向下转型,并使用 Value(..)
、GetValue(..)
、GetString(..)
等。这似乎只是为了访问元素。我错过了什么?
注意: 完整的 MWE 以及 Makefile 可以从 this gist.
中克隆
SelectionVector
存储的是索引,所以类型是unsigned
,下面的工作:
auto arr = std::dynamic_pointer_cast<NumericArray<UInt16Type>>(selected->ToArray());
感谢 Arrow 开发列表中的 Ravindra the answer。
也许我遗漏了一些明显的东西,但就我的生活而言,我无法弄清楚如何在 Gandiva 过滤器操作后访问数组的元素。
我已经链接了一个我这样编译的最小示例:
$ /usr/lib64/ccache/g++ -g -Wall -m64 -std=c++17 -pthread -fPIC \
-I/opt/data-an/include mwe.cc -o mwe \
-L/opt/data-an/lib64 -lgandiva -larrow
然后我 运行 像这样的二进制文件:
$ LD_LIBRARY_PATH=/opt/data-an/lib64 ./mwe
大体上这就是我正在尝试的(随后是 MWE 的摘录):
创建一个 5 元素向量:1, 3, 2, 4, 5
int num_records = 5; arrow::Int64Builder i64builder; ArrayPtr array0; EXPECT_OK(i64builder.AppendValues({1, 3, 2, 4, 5})); EXPECT_OK(i64builder.Finish(&array0));
使用Gandiva获取偶数元素,索引:2、3
// schema for input fields auto field0 = field("f0", arrow::int64()); auto schema = arrow::schema({field0}); // even: f0 % 2 == 0 auto field0_node = TreeExprBuilder::MakeField(field0); auto lit_2 = TreeExprBuilder::MakeLiteral(int64_t(2)); auto remainder = TreeExprBuilder::MakeFunction("mod", {field0_node, lit_2}, int64()); auto lit_0 = TreeExprBuilder::MakeLiteral(int64_t(0)); auto even = TreeExprBuilder::MakeFunction("equal", {remainder, lit_0}, boolean()); auto condition = TreeExprBuilder::MakeCondition(even); // input record batch auto in_batch = arrow::RecordBatch::Make(schema, num_records, {array0}); // filter std::shared_ptr<Filter> filter; EXPECT_OK(Filter::Make(schema, condition, &filter)); std::shared_ptr<SelectionVector> selected; EXPECT_OK(SelectionVector::MakeInt16(num_records, pool_, &selected)); EXPECT_OK(filter->Evaluate(*in_batch, selected));
通过使用来自 Gandiva 过滤器的选择向量作为索引数组来访问原始数组中的偶数元素
// std::cout << "array0[0]: " << array0->Value(0); // doesn't compile // error: ‘using element_type = class arrow::Array’ {aka ‘class // arrow::Array’} has no member named ‘Value’ // downcast it to the correct derived class auto array0_cast = std::dynamic_pointer_cast<NumericArray<Int64Type>>(array0); std::cout << "array0[0]: " << array0_cast->Value(0) << std::endl;
但我似乎无法访问 selection vector 的元素。由于它被声明为 std::shared_ptr<arrow::Array>
,因此未找到 Value(..)
方法。因为我用 SelectionVector::MakeInt16(..)
填充了它,所以我尝试向下转换为 arrow::NumericArray<Int16Type>
,但是失败了!我不确定我哪里出错了。
auto idx_arr_cast = std::dynamic_pointer_cast<NumericArray<Int16Type>>(idx_arr);
if (idx_arr_cast) {
std::cout << "idx_arr[0]: " << idx_arr_cast->Value(0) << std::endl;
} else {
std::cerr << "idx_arr_cast is a nullptr!" << std::endl;
}
我还有一个相关但更笼统的问题。给定一个数组,如果我不知道确切的类型,我就找不到访问元素(或迭代它们)的方法。如果我知道类型,我可以向下转型,并使用 Value(..)
、GetValue(..)
、GetString(..)
等。这似乎只是为了访问元素。我错过了什么?
注意: 完整的 MWE 以及 Makefile 可以从 this gist.
中克隆SelectionVector
存储的是索引,所以类型是unsigned
,下面的工作:
auto arr = std::dynamic_pointer_cast<NumericArray<UInt16Type>>(selected->ToArray());
感谢 Arrow 开发列表中的 Ravindra the answer。