【问题标题】:Writing JSON with dict properties to Google Cloud Datastore将带有 dict 属性的 JSON 写入 Google Cloud Datastore
【发布时间】:2018-11-09 22:57:24
【问题描述】:

使用 Apache Beam(Python 2.7 SDK)我正在尝试将 JSON 文件作为实体写入 Google Cloud Datastore。

示例 JSON:

{
"CustId": "005056B81111",
"Name": "John Smith", 
"Phone": "827188111",
"Email": "john@xxx.com", 
"addresses": [
    {"type": "Billing", "streetAddress": "Street 7", "city": "Malmo", "postalCode": "CR0 4UZ"},
    {"type": "Shipping", "streetAddress": "Street 6", "city": "Stockholm", "postalCode": "YYT IKO"}
]
}

我编写了一个 Apache Beam 管道,主要包含 3 个步骤,

  1. beam.io.ReadFromText(input_file_path)

  2. beam.ParDo(CreateEntities())

  3. WriteToDatastore(项目)

在第 2 步中,我将 JSON 对象(dict)转换为实体,

class CreateEntities(beam.DoFn):
  def process(self, element):
    element = element.encode('ascii','ignore')
    element = json.loads(element)
    Id = element.pop('CustId')
    entity = entity_pb2.Entity()
    datastore_helper.add_key_path(entity.key, 'CustomerDF', Id)
    datastore_helper.add_properties(entity, element)
    return [entity]

这适用于基本属性。但是,由于 address 本身是一个 dict 对象,因此它失败了。 我读过类似的post

但是没有得到转换dict的确切代码->实体

下面尝试将地址元素设置为实体但不起作用,

element['addresses'] = entity_pb2.Entity()

其他参考资料:

【问题讨论】:

    标签: python-2.7 google-cloud-datastore google-cloud-dataflow


    【解决方案1】:

    您是否尝试将其存储为重复的结构化属性?

    ndb.StructuredPropertys 出现在数据流中,键被展平,对于重复的结构化属性,结构化属性对象中的每个单独的属性都成为一个数组。所以我认为你需要这样写:

    datastore_helper.add_properties(entity, {
        ...
        "addresses.type": ["Billing", "Shipping"],
        "addresses.streetAddress": ["Street 7", "Street 6"],
        "addresses.city": ["Malmo", "Stockholm"],
        "addresses.postalCode": ["CR0 4UZ", "YYT IKO"],
    })
    

    或者,如果您尝试将其保存为 ndb.JsonProperty,您可以这样做:

    datastore_helper.add_properties(entity, {
            ...
            "addresses": json.dumps(element['addresses']),
        })
    

    【讨论】:

    • 谢谢@Alex。我现在正在尝试使用 NDB。为此,我使用命令“from google.appengine.ext import ndb”导入 NDB 为此,当我尝试执行“pip install google.appengine.ext”时,它失败说“找不到满足 google.appengine 要求的版本.ext(来自版本:)找不到与 google.appengine.ext 匹配的发行版”我做了,“gcloud components install app-engine-python”但仍然是同样的错误。
    • 哦 ndb 只能从应用引擎标准中使用。但我假设您有一个应用引擎应用程序,您正在尝试将这些记录发送到
    • 不,我没有使用 AppEngine。我正在使用 Python(2.7) SDK 运行 Apache Beam 管道。此管道厌倦了从 Cloud Storage 读取 .JSON 文件并将它们写入 Cloud Datastore。所以从你的回复看来,ndb好像不能用了。
    • 正确,但是一旦这些记录在数据存储中。您打算如何阅读/使用它们?
    • 是的,因为我们有一个 AppEngine 可以从 Datastore 访问记录。它是使用 Node.js 构建的。那么有什么我可以尝试使用 Apache Beam 解决此问题的方法吗?
    【解决方案2】:

    我知道这是一个老问题,但我有一个类似的问题(尽管 Python 3.6 和 NDB)并编写了一个函数来将 dict 中的所有 dicts 转换为 Entity。这使用递归来遍历所有节点,根据需要进行转换:

    def dict_to_entity(data):
    
        # the data can be a dict or a list, and they are iterated over differently
        # also create a new object to store the child objects
        if type(data) == dict:
            childiterator = data.items()
            new_data = {}
        elif type(data) == list:
            childiterator = enumerate(data)
            new_data = []
        else:
            return
    
        for i, child in childiterator:
    
            # if the child is a dict or a list, continue drilling...
            if type(child) in [dict, list]:
                new_child = dict_to_entity(child)
            else:
                new_child = child
    
            # add the child data to the new object
            if type(data) == dict:
                new_data[i] = new_child
            else:
                new_data.append(new_child)
    
        # convert the new object to Entity if needed
        if type(data) == dict:
            child_entity = datastore.Entity()
            child_entity.update(new_data)
            return child_entity
        else:
            return new_data
    

    【讨论】:

      猜你喜欢
      • 2018-11-18
      • 2021-01-01
      • 2015-09-04
      • 2021-02-21
      • 2017-05-07
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多