【问题标题】:How to get filtered data from Bigtable using Python?如何使用 Python 从 Bigtable 中获取过滤后的数据?
【发布时间】:2019-09-11 13:25:20
【问题描述】:

我正在使用 Bigtable 模拟器并已成功在其中添加了一个表,现在我需要获取过滤后的数据。

表格如下:

arc_record_id | record_id | batch_id
1             |624        |86
2             |625        |86
3             |626        |86 

以此类推...直到 arc_record_id 10。

我已经尝试过下面给出的 Python 代码:

visit_dt_filter = ValueRangeFilter(start_value = "1".encode('utf-8'), 
end_value = "2".encode('utf-8'))

col1_filter = ColumnQualifierRegexFilter(b'arc_record_id')

chain1 = RowFilterChain(filters=[col1_filter, visit_dt_filter])

partial_rows = testTable.read_rows(filter_=chain1)

for row in partial_rows:
    cell = row.cells[columnFamilyid1]["arc_record_id".encode('utf-8')][0]
    print(cell.value.decode('utf-8'))

行键是

prim_key=row_value[0] //which is arc_record_id 
row_key="RecordArchive{}".format(prim_key).encode('utf-8') 

我得到的输出为

1
10
2
3

我希望输出是

arc_record_id | record_id | batch_id
1             |624        |86
2             |625        |86

【问题讨论】:

  • 您从查询中得到什么输出?它有效吗?什么是行键?
  • @David 请检查更新后的问题。

标签: python bigtable google-cloud-bigtable


【解决方案1】:

您的代码有几个问题可以帮助您达到您想要的效果:

  1. Bigtable 使用lexicographic sort over arbitrary bytes,因此排序顺序为 1、10、2、3 等。这就是结果集中包含 10 的原因。您可以通过左填充数字来解决此问题,以便将它们存储为 000000001、000000002。(您可以通过存储为十六进制甚至二进制来降低效率低下)。

  2. 因为您只打印row.cells[columnFamilyid1]["arc_record_id".encode('utf-8')],所以您只输出arc_record_id。

  3. 因为要过滤的列是row key,所以直接告诉read_rows要读取的范围既简单又高效:read_rows(start_key="RecordArchive1".encode('utf-8'), end_key="RecordArchive3".encode('utf-8'))

总而言之,试试这样的代码:

KEY_PREFIX = "RecordArchive".encode('utf-8')
ARC_RECORD_ID_COL = "arc_record_id".encode('utf-8')
RECORD_ID_COL = "record_id".encode('utf-8')
BATCH_ID_COL = "batch_id".encode('utf-8')

# Functions used to store/retrieve integer values. Supports IDs up to 2**31
def pack_int(i):
    return struct.pack('>l', i)
def unpack_int(b):
    return struct.unpack('>l', b)[0]
# row key of a record of given arc_record_id
def rowkey(id):
    return KEY_PREFIX + pack_int(id)

results = table.read_rows(start_key=rowkey(1), end_key=rowkey(2), end_inclusive=True)
print("arc_record_id,record_id,batch_id")
for row in results:
    print("{},{},{}".format(
              unpack_int(row.cell[columnFamilyid1][ARC_RECORD_ID_COL][0].value),
              unpack_int(row.cell[columnFamilyid1][RECORD_ID_COL][0].value),
              unpack_int(row.cell[columnFamilyid1][BATCH_ID_COL][0].value)))

【讨论】:

  • 如果我想使用记录 ID 为“625”的“记录 ID”读取行,那么 read_rows() 的代码将如何?提前致谢
  • 由于record_id 不是行键,因此您需要进行表扫描,即带有过滤器的read_rows
  • 我对列 col1_filter = ColumnQualifierRegexFilter(RECORD_ID_COL) 使用了“visit_dt_filter = ValueRangeFilter(start_value = "626", end_value ="626")”,但我只得到那个 RECORD_ID_COL 列。我想要 RECORD_ID_COL 为 626 的所有列。如何使用过滤器获取所有列?这就像我想查询“从 RECORD_ID_COL=626 的表中选择 *”。
  • 很丑:使用ConditionalRowFilter(base_filter=RowFilterChain(filters=[ColumnRangeFilter(start_column=RECORD_ID_COL, end_column=RECORD_ID_COL), ValueRangeFilter(start_filter=pack_int(626), end_filter=pack_int(626))]), true_filter=PassAllFilter())
猜你喜欢
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
相关资源
最近更新 更多