通过云功能将数据从pubsub写入bigtable

时间:2019-12-01 19:19:43

标签: python google-cloud-functions google-cloud-bigtable

我是云计算大表的初学者,使用云功能将数据从pub / sub写入bigtable时遇到了大问题。

云函数从pubsub获取消息,但问题出在下一步,将其写入bigtable。

该消息是使用python脚本创建的,并发送到pub / sub。

一个消息示例:

  

b'{“ eda”:2.015176,“温度”:33.39,“ bvp”:-0.49,“ x_acc”:-36.0,“ y_acc”:-38.0,“ z_acc”:-128.0,“ heart_rate”: 83.78,“ iddevice”:15.0,“ timestamp”:“ 2019-12-01T20:01:36.927Z”}'

为了将其写入bigtable,我创建了一个表:

 from google.cloud import bigtable 
 from google.cloud.bigtable import column_family

 client = bigtable.Client(project="projectid", admin=True) 
 instance = client.instance("bigtableinstance")
 table = instance.table("bigtable1")
 print('Creating the {} table.'.format(table)) 
 print('Creating columnfamily cf1 with Max Version GC rule...')
 max_versions_rule = column_family.MaxVersionsGCRule(2)
 column_family_id = 'cf1'
 column_families = {column_family_id: max_versions_rule}
 if not table.exists():
     table.create(column_families=column_families)
     print("Table {} is created.".format(table)) 
 else:
     print("Table {} already exists.".format(table))

这没有问题。

现在,我尝试使用main方法在云函数中通过以下python代码通过pub / sub将消息写入bigtable:

import json
import base64
import os
from google.cloud import bigtable
from google.cloud.bigtable import column_family, row_filters


project_id = os.environ.get('projetid', 'UNKNOWN')
INSTANCE = 'bigtableinstance'
TABLE = 'bigtable1'

client = bigtable.Client(project=project_id, admin=True)
instance = client.instance(INSTANCE)

colFamily = "cf1"
def writeToBigTable(table, data):
#    Parameters row_key (bytes) – The key for the row being created.
#    Returns A row owned by this table.
        row_key = data[colFamily]['iddevice'].value.encode()
        row = table.row(row_key)
        for colFamily in data.keys():
            for key in data[colFamily].keys():
                row.set_cell(colFamily,
                                        key,
                                        data[colFamily][key])
        table.mutate_rows([row])
        return data

def selectTable():
    stage = os.environ.get('stage', 'dev')
    table_id = TABLE + stage
    table = instance.table(table_id)
    return table


def main(event, context):
    data = base64.b64decode(event['data']).decode('utf-8')
    print("DATA: {}".format(data))
    eda, temperature, bvp, x_acc, y_acc, z_acc, heart_rate, iddevice, timestamp = data.split(',')

    table = selectTable()

    data = {'eda': eda,
         'temperature': temperature,
         'bvp': bvp,
         'x_acc':x_acc,
         'y_acc':y_acc,
         'z_acc':z_acc,
         'heart_rate':heart_rate,
         'iddevice':iddevice,
         'timestamp':timestamp}
    writeToBigTable(table, data)
    print("Data Written: {}".format(data))

我尝试了不同的版本,但是找不到解决方案。

感谢您的帮助。

祝一切顺利

多米尼克

2 个答案:

答案 0 :(得分:2)

我认为这行是错误的:

    row_key = data[colFamily]['iddevice'].value.encode()

您正在传递数据对象,但是它没有'cf1'属性。您也不必对其进行编码。试试看:

    row_key = data['iddevice']

您的for循环也会遇到相同的问题。我想这就是你想要的

    for col in data.keys():
        row.set_cell(colFamily, key, data[key])

此外,我知道您只是在玩它,但是使用设备ID作为行键的唯一值的结果将很糟糕。建议将行键和日期或其他属性之一(取决于查询)结合起来,然后将其用作行键。 Cloud Bigtable schema上有一个文档是有帮助的,而codelab则使用了更现实的示例数据集,并逐步介绍了如何为该示例选择架构。它使用Java,但是您仍然可以导入数据并运行自己的查询。

答案 1 :(得分:0)

首先非常感谢您的帮助。

我尝试通过代码建议()修复它,但是很遗憾,由于其他错误,该代码现在无法正常工作。

  

AttributeError:“ DirectRow”对象没有属性“ append”

我想这在下面的代码行之内

        row.set_cell(colFamily,
                     key,
                     data[key])

我可以想象错误的根源在于字符串“ data”的分割

eda, temperature, bvp, x_acc, y_acc, z_acc, heart_rate, iddevice, timestamp = data.split(',')

例如eda看起来像这样:

"'eda':2.015176"

我觉得这很不对。

尤其是当我将其插入以下字典中时:

 data = {'eda': eda,....}

错误

  

AttributeError:“ DirectRow”对象没有属性“ append”   似乎在说,我要使用set_cell处理的数据有问题。有set_cell,其中row作为列表或Direct Row Instance的任何其他可迭代项。不适合使用dic吗?

我尝试了一种使用列表的解决方法,但这似乎使情况变得更糟。

client = bigtable.Client(project=project_id, admin=True)
instance = client.instance(INSTANCE)

colFamily = "cf1"
def writeToBigTable(table, dat):

    row_key = "{}-{}".format(dat[16], dat[17])
    row = table.row(row_key)
    for n in range(len(dat)):
        row.set_cell(colFamily,
                     dat[n],
                     dat[n+9])
    table.mutate_rows([row])
    return dat

def selectTable():
    stage = os.environ.get('stage', 'dev')
    table_id = TABLE + stage
    table = instance.table(table_id)
    return table


def main(event, context):
    data = base64.b64decode(event['data']).decode('utf-8')
    print("DATA: {}".format(data))
    var_1, eda, var_2, temperature, var_3, bvp, var_4, x_acc, var_5, y_acc, var_6, z_acc, var_7, heart_rate, var_8, iddevice, var_9, timestamp = data.replace(':',',').split(',')

    table = selectTable(); dat = [var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9, eda, temperature, bvp, x_acc, y_acc, z_acc, heart_rate, iddevice, timestamp]; 

#   data = {'eda': eda,
#         'temperature': temperature,
#         'bvp': bvp,
#         'x_acc':x_acc,
#         'y_acc':y_acc,
#         'z_acc':z_acc,
#         'heart_rate':heart_rate,
#         'iddevice':iddevice,
#         'timestamp':timestamp}
    writeToBigTable(table, dat)
    print("Data Written: {}".format(data))

我真的很难解决这个问题,也没有进一步解决该问题的想法。