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 等年龄,以确保过滤器正常工作。