Python BigTable 客户端 "And" 将 return 所有单元格的过滤器
Python BigTable Client "And" Filter that will return all cells
我似乎无法弄清楚如何创建正确的过滤器来实现等同于以下 MySQL 查询的结果。
select * from TABLE where age >= 10 AND height < 60
在 Python BigTable 方面,我的第一个想法是使用下面的代码片段,但它 returns 没有结果。值得注意的是,当我单独使用任一过滤器时,我 DO 得到了结果,但是当组合它们时,我没有得到任何结果。
如有任何帮助,我们将不胜感激。
# create the age filter
age_filt = btf.RowFilterChain([
btf.ColumnQualifierRegexFilter(COL_AGE),
btf.ValueRangeFilter(
start_value=struct.pack("Q", 10) )
])
# create the height filter
height_filt = btf.RowFilterChain([
btf.ColumnQualifierRegexFilter(COL_HEIGHT),
btf.ValueRangeFilter(
end_value=struct.pack("Q", 60) )
])
# THIS filter results in no results being returned
val_chain = btf.RowFilterChain([
age_fil, height_filt
])
# this is a trick to get all the fields
# Maybe there is a better way
cond = btf.ConditionalRowFilter(
base_filter=val_chain,
true_filter=btf.PassAllFilter(True))
# Read full table
partial_rows = tbl.read_rows(
start_key=start_key,
end_key=end_key,
filter_=cond
)
我认为这里的问题是 ColumnQualifierRegexFilter 仅 returns 来自匹配列的单元格,而不是整行。
这就是需要 ConditionalRowFilter 的原因。也可以看看:
How to get filtered data from Bigtable using Python?
请注意,创建复杂的过滤器链会对查询的性能产生负面影响,并且某些过滤器的性能不如其他过滤器。在某些情况下,简单地检索更广泛的数据并在客户端进行过滤可以产生更好的性能。此外,如果您发现自己需要构建非常复杂的 SQL 之类的查询,请考虑 Cloud Spanner 或 BigQuery 是否更适合您的用例。
问题是您使用的是链条。您的 age_filt 将输出年龄列中的一个元素,然后 将被 height_filt 过滤掉 ,因为它只接受身高列中的元素。
要模拟 AND,您需要做一些更神秘的事情。请原谅伪代码:
Condition(
filter=Chain(
// Return exactly one item for each filter which passes
Union(
// Return exactly one item if the age filter passes
Chain(Column(COL_AGE), ValueRange(>=10), CellsColumnLimit(1)),
// Return exactly one item if the height filter passes
Chain(Column(COL_HEIGHT), ValueRange(<60), CellsColumnLimit(1)),
),
// Skip the first element, so we only emit something if both filters pass
CellsRowOffset(1)),
true=PassAll())
您可以对您可能想要执行的任何类型的 AND 构造使用类似的模式。这当然是一个巨大的麻烦。在 Bigtable 中以这种方式工作的原因是过滤器语言被设计为完全可流式传输。换句话说,您的节点可以计算此 AND 语句,同时一次只在内存中保存一个单元格,而不是缓冲整行。条件过滤器是这里唯一的例外,这也是它们 tend to be slow.
的原因
无关,但在对数字执行 ValueRangeFilter 时,始终确保使用固定宽度编码。因此,例如,如果 100 岁是可能的,您应该编码 006、052 等年龄,以确保过滤器正常工作。
我似乎无法弄清楚如何创建正确的过滤器来实现等同于以下 MySQL 查询的结果。
select * from TABLE where age >= 10 AND height < 60
在 Python BigTable 方面,我的第一个想法是使用下面的代码片段,但它 returns 没有结果。值得注意的是,当我单独使用任一过滤器时,我 DO 得到了结果,但是当组合它们时,我没有得到任何结果。
如有任何帮助,我们将不胜感激。
# create the age filter
age_filt = btf.RowFilterChain([
btf.ColumnQualifierRegexFilter(COL_AGE),
btf.ValueRangeFilter(
start_value=struct.pack("Q", 10) )
])
# create the height filter
height_filt = btf.RowFilterChain([
btf.ColumnQualifierRegexFilter(COL_HEIGHT),
btf.ValueRangeFilter(
end_value=struct.pack("Q", 60) )
])
# THIS filter results in no results being returned
val_chain = btf.RowFilterChain([
age_fil, height_filt
])
# this is a trick to get all the fields
# Maybe there is a better way
cond = btf.ConditionalRowFilter(
base_filter=val_chain,
true_filter=btf.PassAllFilter(True))
# Read full table
partial_rows = tbl.read_rows(
start_key=start_key,
end_key=end_key,
filter_=cond
)
我认为这里的问题是 ColumnQualifierRegexFilter 仅 returns 来自匹配列的单元格,而不是整行。
这就是需要 ConditionalRowFilter 的原因。也可以看看: How to get filtered data from Bigtable using Python?
请注意,创建复杂的过滤器链会对查询的性能产生负面影响,并且某些过滤器的性能不如其他过滤器。在某些情况下,简单地检索更广泛的数据并在客户端进行过滤可以产生更好的性能。此外,如果您发现自己需要构建非常复杂的 SQL 之类的查询,请考虑 Cloud Spanner 或 BigQuery 是否更适合您的用例。
问题是您使用的是链条。您的 age_filt 将输出年龄列中的一个元素,然后 将被 height_filt 过滤掉 ,因为它只接受身高列中的元素。
要模拟 AND,您需要做一些更神秘的事情。请原谅伪代码:
Condition(
filter=Chain(
// Return exactly one item for each filter which passes
Union(
// Return exactly one item if the age filter passes
Chain(Column(COL_AGE), ValueRange(>=10), CellsColumnLimit(1)),
// Return exactly one item if the height filter passes
Chain(Column(COL_HEIGHT), ValueRange(<60), CellsColumnLimit(1)),
),
// Skip the first element, so we only emit something if both filters pass
CellsRowOffset(1)),
true=PassAll())
您可以对您可能想要执行的任何类型的 AND 构造使用类似的模式。这当然是一个巨大的麻烦。在 Bigtable 中以这种方式工作的原因是过滤器语言被设计为完全可流式传输。换句话说,您的节点可以计算此 AND 语句,同时一次只在内存中保存一个单元格,而不是缓冲整行。条件过滤器是这里唯一的例外,这也是它们 tend to be slow.
的原因无关,但在对数字执行 ValueRangeFilter 时,始终确保使用固定宽度编码。因此,例如,如果 100 岁是可能的,您应该编码 006、052 等年龄,以确保过滤器正常工作。