3

我有这个 json 模式

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

我想把它摄取到一个比诺表中来运行一个查询

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

有没有办法在黑皮诺工作中做到这一点?

4

1 回答 1

5

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

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

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

请参阅下面的列subjects_name和如何subjects_grade定义。由于它是一个数组,所以这两个字段都是 Pinot 中的多值列。

2.直接摄取JSON记录

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

  • 将表模式中的 JSON 字段定义为具有 maxLength 值的字符串
  • 将此字段放入表配置中的noDictionaryColumnsjsonIndexColumns
  • 定义转换函数jsonFormat以对表配置中的 JSON 字段进行字符串化

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

下面是示例表架构/配置/查询:

示例黑皮诺模式:

{
  "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"
}

示例表配置:

{
    "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 JSON 函数

Pinot JSON 索引

Pinot 多值函数

于 2021-01-26T09:44:48.463 回答