使用pyspark-Databricks从事件中心处理事件

时间:2019-01-12 04:41:54

标签: json apache-spark spark-streaming azure-eventhub

我有一个Mongo更改流(一个pymongo应用程序),该流在不断获取集合中的更改。程序收到的这些更改文档将发送到Azure事件中心。 Spark笔记本必须在进入Event Hub时读取文档,并与该集合的Spark表进行模式匹配(将文档中的字段与spark表列匹配)。如果文档中的字段少于表格中的字段,则必须使用Null添加列。

我正在从事件中心读取事件,如下所示。

spark.readStream.format("eventhubs").option(**config).load().

如文档中所述,原始消息位于要转换为字符串的数据框的“ body”列中。现在,我在流数据框中将Mongo文档作为JSON字符串获取。我面临以下问题。

我需要提取mongo文档中的各个字段。需要比较火花表中存在的字段和Mongo文档中不存在的字段。我看到了一个名为get_json_object(col,path)的函数。这实际上会再次返回一个字符串,我无法单独选择所有列。

如果from_json可用于将JSON字符串转换为Struct类型,则我无法指定Schema,因为我们有近70个集合(也有相应数量的spark表)向每个Mongo文档发送了10至450字段。 / p>

如果我可以将流数据帧中的JSON字符串转换为可以通过数据帧推断其模式的JSON对象(例如read.json可以执行的操作),则可以使用SQL *表示法提取各个列,只需执行几步操作,然后将最终数据帧保存到spark表。有可能这样做吗?我在犯什么错误?

注意:Stram DF不支持collect()方法从基础rdd单独提取JSON字符串并进行必要的列比较。在Azure Databricks环境4.3中使用Spark 2.4和Python。

下面是从事件中心读取事件并将其转换为字符串后在笔记本中获得的示例数据。

{
  "documentKey": "5ab2cbd747f8b2e33e1f5527",
  "collection": "configurations",
  "operationType": "replace",
  "fullDocument": {
    "_id": "5ab2cbd747f8b2e33e1f5527",
    "app": "7NOW",
    "type": "global",
    "version": "1.0",
    "country": "US",
    "created_date": "2018-02-14T18:34:13.376Z",
    "created_by": "Vikram SSS",
    "last_modified_date": "2018-07-01T04:00:00.000Z",
    "last_modified_by": "Vikram Ganta",
    "last_modified_comments": "Added new property in show_banners feature",
    "is_active": true,
    "configurations": [
      {
        "feature": "tip",
        "properties": [
          {
            "id": "tip_mode",
            "name": "Delivery Tip Mode",
            "description": "Tip mode switches the display of tip options between percentage and amount in the customer app",
            "options": [
              "amount",
              "percentage"
            ],
            "default_value": "tip_percentage",
            "current_value": "tip_percentage",
            "mode": "multiple or single"
          },
          {
            "id": "tip_amount",
            "name": "Tip Amounts",
            "description": "List of possible tip amount values",
            "default_value": 0,
            "options": [
              {
                "display": "No Tip",
                "value": 0
              }
            ]
          }
        ]
      }
    ]
  }
}

我想分开并取出上面示例中的full_document。当我使用get_json_object时,我将在另一个流数据框中获取full_document作为JSON字符串而不是作为对象。如您所见,在full_document中有一些我可以爆炸的数组类型(文档说,在流DF中支持explode,但是还没有尝试过),但是我也想提取一些对象(例如struct type)领域。我不能使用SQL'*'表示法,因为get_json_object返回的是字符串,而不是对象本身。

1 个答案:

答案 0 :(得分:0)

令人信服的是,使用显式提到的模式,JSON的这种多变的模式会更好。所以我认为,在流环境中,传入流的模式非常不同,指定模式总是更好。因此,我将继续进行get_json_object和from_json并通过文件读取架构。