Pinot 嵌套 json 摄取

Pinot nested json ingestion

我有这个 json 架构

{
  "name":"Pete"
  "age":24,
  "subjects":[
    {
      "name":"maths"
      "grade":"A"
    },
    {
      "name":"maths"
      "grade":"B"
    }
  ]
}

我想将它吸收到 pinot table 到 运行 这样的查询

select age,subjects_grade,count(*) from table group by age,subjects_grade

有没有办法在 pinot 工作中做到这一点?

Pinot 有两种处理 JSON 条记录的方法:

1.在摄取时间内压平记录: 在这种情况下,我们将每个嵌套字段视为一个单独的字段,因此需要:

  • 在 table 模式中定义那些字段
  • 在 table 配置中定义转换函数以展平嵌套字段

请参阅下面如何定义列 subjects_namesubjects_grade。因为是数组,所以Pinot中这两个字段都是多值列。

2。直接提取 JSON 条记录

在这种情况下,我们将每个嵌套字段视为一个单独的字段,因此需要:

  • 将 table 架构中的 JSON 字段定义为具有 maxLength 值的字符串
  • 将此字段放入 noDictionaryColumnsjsonIndexColumns in table config
  • 定义转换函数 jsonFormat 以将 table 配置中的 JSON 字段字符串化

请参阅下面如何定义第 subjects_str 列。

下面是示例 table schema/config/query:

示例 Pinot 架构:

{
  "metricFieldSpecs": [],
  "dimensionFieldSpecs": [
    {
      "dataType": "STRING",
      "name": "name"
    },
    {
      "dataType": "LONG",
      "name": "age"
    },
    {
      "dataType": "STRING",
      "name": "subjects_str"
    },
    {
      "dataType": "STRING",
      "name": "subjects_name",
      "singleValueField": false
    },
    {
      "dataType": "STRING",
      "name": "subjects_grade",
      "singleValueField": false
    }
  ],
  "dateTimeFieldSpecs": [],
  "schemaName": "myTable"
}

示例Table 配置:

{
    "tableName": "myTable",
    "tableType": "OFFLINE",
    "segmentsConfig": {
        "segmentPushType": "APPEND",
        "segmentAssignmentStrategy": "BalanceNumSegmentAssignmentStrategy",
        "schemaName": "myTable",
        "replication": "1"
    },
    "tenants": {},
    "tableIndexConfig": {
        "loadMode": "MMAP",
        "invertedIndexColumns": [],
        "noDictionaryColumns": [
            "subjects_str"
        ],
        "jsonIndexColumns": [
            "subjects_str"
        ]
    },
    "metadata": {
        "customConfigs": {}
    },
    "ingestionConfig": {
        "batchIngestionConfig": {
            "segmentIngestionType": "APPEND",
            "segmentIngestionFrequency": "DAILY",
            "batchConfigMaps": [],
            "segmentNameSpec": {},
            "pushSpec": {}
        },
        "transformConfigs": [
            {
                "columnName": "subjects_str",
                "transformFunction": "jsonFormat(subjects)"
            },
            {
                "columnName": "subjects_name",
                "transformFunction": "jsonPathArray(subjects, '$.[*].name')"
            },
            {
                "columnName": "subjects_grade",
                "transformFunction": "jsonPathArray(subjects, '$.[*].grade')"
            }
        ]
    }
}

示例查询:

select age, subjects_grade, count(*) from myTable GROUP BY  age, subjects_grade

select age, json_extract_scalar(subjects_str, '$.[*].grade', 'STRING') as subjects_grade, count(*) from myTable GROUP BY  age, subjects_grade

比较两种方式,我们推荐解决方案 1 以在字段密度高时展平嵌套字段(例如,每个文档都有字段 namegrade,那么值得将它们提取出来作为新列),它提供了更好的查询性能和更好的存储效率。

对于解决方案2,它的配置更简单,并且适用于稀疏字段(例如只有少数文档有某些字段)。需要使用json_extract_scalar函数来访问嵌套字段。

另请注意 Pinot GROUP BY 在多值列上的行为。

更多参考资料:

Pinot Column Transformation

Pinot JSON Functions

Pinot JSON Index

Pinot Multi-value Functions