06_Hudi ケースの戦闘、Apache Flume ログ収集、SparkSession データ処理、Kafka へのデータ、Hudi テーブルの保存、Hive インジケーター分析の統合、Hudi テーブル データのロード、FineBI レポートの視覚化など。

この記事は「ダークホース プログラマー」hudi コースからのものです

6. 第 6 章 Hudi ケーススタディ
6.1 ケースアーキテクチャ
6.2 ビジネスデータ
6.2.1 メッセージデータ形式
6.2.2 データ生成
6.3 Qimo データ収集
6.3.1 Apache Flume とは
6.3.2 Apache Flume 動作メカニズム
6.3.3 Apache Flume インストール展開6. 3.4
Apache Flume エントリ
プログラム6.3.5 Qimo ソーシャル データの収集6.3.5
Qimo ソーシャル データの収集
6.4.1 モジュールの作成6.4.2エンティティ
クラスのカプセル化
6.4.3 ストリーミング プログラムの作成6.4.3.1
SparkSession インスタンス オブジェクトの構築
6.4 .3.2 Kafka データの消費
6.4.3.3 印刷コンソール
6.4.3.4 データ分析と変換
6.4.3.5 Hudi テーブルの保存
6.4.4 ストリーミング プログラムの実行
6.5 統合された Hive インジケーター分析
6.5.1 Hive テーブルの作成
6.5.2 ビジネス インジケーター分析
6.6 Spark オフライン インデックス分析
6.6.1 要件の説明
6.6.2データベーステーブルの作成
6.6.3 インデックス分析プログラムの書き込み
6.6.3.1 Hudi テーブルデータのロード
6.6.3.2 IP アドレスの解析とフィールドの選択
6.6.3.3 ビジネス指標の分析
6.6.4 レポート プログラムの操作
6.7 FineBI レポートの視覚化
6.7.1 FineBI のインストール
6.7.2 データ ソースの構成6.7.3
データ セットの追加6.7.4
ダッシュボードの作成
6.7.5 縦棒グラフ: 上位 10 ユーザーが情報を送信する 第
6.7巻.6 円グラフ: 上位 10 州の情報量
6.7.7 マップ: 各州の情報量

6. 第 6 章 Hudi のケーススタディ

Qimo Social はカスタマー サービス システムを専門とする会社です。Chuanzhi Education は Qimo Social をベースにしたカスタマー サービス システムを構築しています。毎日多くのユーザーがチャットしています。Chuanzhi Education は現在、これらのチャット記録を保存したいと考えています。日々のメッセージ量の統計分析が必要な場合、データの保存とデータのリアルタイム統計分析を実現する方法を設計してください。
要件は次のとおりです。

    1. データ ストレージに適切なストレージ コンテナーを選択し、基本的なデータ クエリ作業をサポートさせます。
    1. メッセージの総量に関するリアルタイムの統計を実行します。
    1. 各リージョンで送受信されたメッセージの総量のリアルタイム統計
    1. 各顧客が送受信したメッセージ数のリアルタイム統計

6.1 ケースのアーキテクチャ

Qimo ユーザーのチャット情報データをリアルタイムで収集し、メッセージ キューを Kafka に保存し、データをリアルタイムで処理して変換し、メッセージを Hudi テーブルに保存し、最後に Hive と Spark を使用してビジネス指標の統計を作成し、表示します。 FanBIビジュアルレポートに基づく。
ここに画像の説明を挿入

  • 1. Apache Flume: 分散型リアルタイムログデータ収集フレーム
    ワーク ビジネス側のデータはディレクトリ内に継続的に生成されるため、リアルタイムでデータを収集する必要があり、flume はファイルの監視などのデータ収集に特化したツールです。新しいファイルが生成されるとすぐに、特定のディレクトリを収集できます。

  • 2. Apache Kafka: 分散メッセージ キュー
    Flume 収集プロセス。メッセージが非常に高速な場合、Flume はデータも効率的に収集します。その場合、データを迅速に運ぶことができるコンテナが必要になります。また、データは後で処理して変換する必要があります。このとき、flumeで収集したデータをKafkaに書き込んでメッセージデータを送信することができ、またKafkaはグループセンター全体の全業務が統一して後続業務(オフラインまたはリアルタイム)につなげるために利用するメッセージシステムでもあります。

  • 3. Apache Spark: 分散メモリ コンピューティング エンジン、オフラインおよびストリーミング データの分析と Qimo ソーシャル ケース全体の処理。
    これにはリアルタイムの収集が必要であるため、現時点では 1 つのデータを処理する必要があり、もう 1 つのデータを処理する必要があることを意味します。場合によっては、Structured Streaming や Flink などのストリーム処理フレームワークが必要になることがあります。
    さらに、Qimo の場合、毎日のユーザー メッセージ データがビジネス指標に基づいて分析され、最終的に MySQL データベースに保存されるため、SparkSQL が選択されます。

  • 4. Apache Hudi: Data Lake Framework
    Qimo ユーザーのチャット メッセージ データは、最終的に Hudi テーブル (基盤となるストレージ: HDFS 分散ファイル システム) に保存され、データ ファイルを一元管理され、その後ビジネス指標分析のために Spark および Hive と統合されます。


  • 5. Apache Hive: Hudi テーブルと統合されたビッグ データ データ ウェアハウス フレームワーク。Qimo チャット データを分析するには、SQL を直接記述するだけです。

  • 6. MySQL: リレーショナル データベース
    ビジネス指標の分析結果を MySQL データベースに保存します。後で指標レポートを表示する場合に便利です。

  • 7. FineBI: レポーティングツール
    Fanruan Company の商用チャート作成ツールで、チャート作成が簡単になります。

6.2 ビジネスデータ

この場合、Qimo ソーシャル ニュース データの生成に特別に使用されるツールを直接提供し、データ生成のためにビジネス側に直接デプロイしてから、データ生成用のツール jar パッケージをデプロイします。

6.2.1 メッセージのデータ形式

ユーザー チャット データは、次の図に示すように、20 個のフィールドを含むテキスト形式でログ ファイルに保存されます。
ここに画像の説明を挿入

サンプルデータ:
ここに画像の説明を挿入
上記データの各フィールド間の区切り記号は、\001です。

6.2.2 データ生成

jar パッケージ 7Mo_DataGen.jar を実行し、パラメータ情報を指定して、ユーザー チャット情報データをシミュレートおよび生成し、ログ ファイルに書き込みます。
ここに画像の説明を挿入

  • 最初のステップでは、元のファイル ディレクトリを作成します。
mkdir -p /export/data/7mo_init
  • 2 番目のステップでは、シミュレーション データ プログラムをアップロードします。
cd /export/data/7mo_init
rz

ここに画像の説明を挿入

  • 3 番目のステップでは、シミュレーション データ ディレクトリを作成します。
mkdir -p /export/data/7mo_data

ここに画像の説明を挿入

  • 4 番目のステップでは、プログラムを実行してデータを生成します。
# 1. 语法
java -jar /export/data/7mo_init/7Mo_DataGen.jar 原始数据路径 模拟数据路径 随机产生数据间隔ms时间
  	
# 2. 测试:每500ms生成一条数据
java -jar /export/data/7mo_init/7Mo_DataGen.jar \
/export/data/7mo_init/7Mo_Data.xlsx \
/export/data/7mo_data \
500
  • 5 番目のステップでは、生成されたデータを表示します。
    ここに画像の説明を挿入

6.3 Qimo データ収集

Qimo はユーザー数が多くアクティビティが高いため、チャット情報データは比較的大きく (1 日あたり 25 GB ~ 30 GB)、データはリアルタイムで収集されます。ここではフレームワークとして Apache Flume を選択します。

6.3.1 Apache Flumeとは

Aapche Flume は、Cloudera が提供する可用性と信頼性の高い分散型大規模ログ収集、集約、送信ソフトウェアです。URL: http://flume.apache.org/
ここに画像の説明を挿入

Flume的核心是把数据从数据源(source)收集过来,再将收集到的数据送到指定的目的地(sink)。为了保证输送的过程一定成功,在送到目的地(sink)之前,会先缓存数据(channel),待数据真正到达目的地(sink)后,flume在删除自己缓存的数据。

ここに画像の説明を挿入

当前Flume有两个版本:
  • Flume 0.9X バージョンは、総称して Flume OG (オリジナル世代) と呼ばれます。
  • Flume 1.X バージョンは、Flume NG (次世代) と総称されます。
    これは、Flume NG がコア コンポーネント、コア構成、コード アーキテクチャの再構築を行っており、Flume OG とは大きく異なるためです。変更のもう 1 つの理由は、Apache 傘下に Flume を組み込むことであり、Cloudera Flume は Apache Flume に名前が変更されました。

6.3.2 Apache Flumeの動作仕組み

Flume システムの中核となる役割はエージェントであり、エージェント自体は通常ログ収集ノード上で実行されるJava プロセスです。
ここに画像の説明を挿入

各エージェントはデータ送信機に相当し、内部には次の 3 つのコンポーネントがあります。

  • ソース: コレクション ソース。データ ソースに接続してデータを取得するために使用されます。
  • シンク: 収集されたデータを送信する目的のシンク場所。次のレベルのエージェントまたは最終ストレージ システムにデータを送信するために使用されます。
  • チャネル: ソースからシンクへデータを転送するために使用されるエージェント内のデータ伝送チャネル。
    データ伝送のプロセス全体において、フローはイベントであり、Flume 内部データ伝送の最も基本的な単位です。
    ここに画像の説明を挿入

イベントは送信データをカプセル化します。テキスト ファイルの場合、通常はレコードの行です。イベントはトランザクションの基本単位でもあります。イベントはソースからチャネル、そしてシンクへと流れ、バイト配列であり、ヘッダー (ヘッダー情報) 情報を運ぶことができます。イベントは、外部データ ソースから外部宛先までのデータの完全な最小単位を表します。
ここに画像の説明を挿入

完全なイベントには、イベント ヘッダー、イベント本文が含まれます。イベント本文は、flume によって収集された日記レコードです。

6.3.3 Apache Flume のインストールとデプロイメント

Apache Flume のインストールは非常に簡単です。直接解凍して、JDK 環境変数を設定するだけです。
最初のステップ、アップロードと解凍

# 上传
cd /export/software
rz apache-flume-1.9.0-bin.tar.gz

# 解压,重命名及创建软链接
tar -zxf apache-flume-1.9.0-bin.tar.gz -C /export/server

cd /export/server
mv apache-flume-1.9.0-bin flume-1.9.0-bin
ln -s flume-1.9.0-bin flume

2 番目のステップでは、flume-env.sh を変更します。

cd /export/server/flume/conf
mv flume-env.sh.template  flume-env.sh

vim flume-env.sh
# 22行:修改JDK路径
export JAVA_HOME=/export/server/jdk

ここに画像の説明を挿入

6.3.4 Apache Flume 入門プログラム

要件の説明: サーバー上の特定のポート番号 (例: 44444) をリッスンし、このポートに送信されたデータを収集します。
ここに画像の説明を挿入

  • ステップ 1. 3 つの主要コンポーネントを決定する
  1. ソースコンポーネント
    : Apache Flume によって提供される、ポート番号をリッスンできるコンポーネント (ネットワークコンポーネント) が必要です: NetCat TCP Source
    ここに画像の説明を挿入

  2. チャネル コンポーネント: Apache Flume を使用して提供する、より高速な送信パイプライン (メモリ コンポーネント) が必要です
    : メモリ チャネル

  3. シンク コンポーネント: ここでは、Apache Flume によって提供される (ログ コンポーネント) を印刷するだけで済みます
    : Logger Sink

  • ステップ 2. 収集構成ファイルを作成します: netcat_source_logger_sink.properties
cd /export/server/flume/conf
vim netcat_source_logger_sink.properties

内容は以下の通りです。

# 第一部分: 定义这个agent中各组件的名字
a1.sources = r1
a1.sinks = k1
a1.channels = c1

#第二部分:  描述和配置source组件:r1
a1.sources.r1.type = netcat
a1.sources.r1.bind = node1.itcast.cn
a1.sources.r1.port = 44444

# 第三部分: 描述和配置sink组件:k1
a1.sinks.k1.type = logger

# 第四部分: 描述和配置channel组件,此处使用是内存缓存的方式
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# 第五部分: 描述和配置source  channel   sink之间的连接关系
a1.sources.r1.channels = c1 
a1.sinks.k1.channel = c1
  • ステップ 3、flume を開始します: 取得設定ファイルを指定します
/export/server/flume/bin/flume-ng agent -n a1  \
-c conf -f /export/server/flume/conf/netcat_source_logger_sink.properties \
-Dflume.root.logger=INFO,console

参数说明: 	
  -c conf   指定flume自身的配置文件所在目录	
  -f conf/netcat-logger.con  指定我们所描述的采集方案	
  -n a1  指定我们这个agent的名字
  • ステップ 4、次のテスト: 接続テストを開始する必要がある場合は、
    まずエージェントが収集および監視するポートにデータを送信して、エージェントが収集するデータを取得できるようにする必要があります。
  1. Telnetをインストールする
yum -y install telnet
  1. エージェント ノードと通信できる任意のマシンで、次のコマンドを実行します。
telnet node1.itcast.cn  44444

ここに画像の説明を挿入

6.3.5 Qimo ソーシャル データの収集

Qimoソーシャルデータソースの特徴: 特定のディレクトリ内のファイルにメッセージを継続的に出力します。機能要件: 特定のディレクトリ内のファイルをリアルタイムで監視し、新しいファイルが見つかるとすぐに Kafka に収集します。
ここに画像の説明を挿入

  • ステップ 1. 3 つの主要コンポーネントを決定する
  1. ソースコンポーネント: 特定のディレクトリを監視できるファイルソースコンポーネントは
    Apache Flume によって提供されます: taildir
  2. チャネル コンポーネント: 通常、Apache Flume によって提供される (より効率的な) メモリ コンポーネントが選択されます
    : メモリ チャネル
  3. シンク コンポーネント: Kafka に出力するシンク コンポーネントは、
    Apache Flume によって提供されます: Kafka シンク
  • ステップ 2. コレクション構成ファイルを作成します: 7mo_mem_kafka.properties
vim /export/server/flume/conf/7mo_mem_kafka.properties

内容は以下の通りです。

# define a1
a1.sources = s1 
a1.channels = c1
a1.sinks = k1

#define s1
a1.sources.s1.type = TAILDIR
#指定一个元数据记录文件
a1.sources.s1.positionFile = /export/server/flume/position/taildir_7mo_kafka.json
#将所有需要监控的数据源变成一个组
a1.sources.s1.filegroups = f1
#指定了f1是谁:监控目录下所有文件
a1.sources.s1.filegroups.f1 = /export/data/7mo_data/.*
#指定f1采集到的数据的header中包含一个KV对
a1.sources.s1.headers.f1.type = 7mo
a1.sources.s1.fileHeader = true

#define c1
a1.channels.c1.type = memory
a1.channels.c1.capacity = 10000
a1.channels.c1.transactionCapacity = 1000

#define k1
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.topic = 7MO-MSG
a1.sinks.k1.kafka.bootstrap.servers = node1.itcast.cn:9092
a1.sinks.k1.kafka.flumeBatchSize = 10
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 100

#bind
a1.sources.s1.channels = c1
a1.sinks.k1.channel = c1
  • ステップ 3、ZK サービスと Kafka サービスを開始する
/export/server/zookeeper/bin/zkServer.sh start 
/export/server/kafka/bin/kafka-server-start.sh -daemon /export/server/kafka/config/server.properties
  • ステップ 4、トピックを作成する
/export/server/kafka/bin/kafka-topics.sh --create \
--topic 7MO-MSG  --partitions 3 --replication-factor 2 \
--bootstrap-server node1.itcast.cn:9092
  • ステップ 5、flume を開始します: 取得設定ファイルを指定します
/export/server/flume/bin/flume-ng agent \
-n a1 -c /export/server/flume/conf/ \
-f /export/server/flume/conf/7mo_mem_kafka.properties \
-Dflume.root.logger=INFO,console
  • ステップ 6. データのシミュレーションを開始する
java -jar /export/data/7mo_init/7Mo_DataGen.jar \
/export/data/7mo_init/7Mo_Data.xlsx \
/export/data/7mo_data \
5000

Kafka トピックにデータがあるかどうかを確認します。
ここに画像の説明を挿入

6.4 Qimo データのリアルタイム保存

Spark でストリーミング プログラム (StructuredStreaming) を作成し、変換 (データ フィールドの抽出など) 後に Kafka の消費からソーシャル データをリアルタイムで取得し、最後にそれを Hudi テーブル (テーブルの形式: ROM) に保存します。
ここに画像の説明を挿入

6.4.1 モジュールの作成

Maven モジュール モジュールを作成し、Spark フレームワークに基づいてプログラムを作成し、関連する依存関係を追加します。プロジェクトの構造は次のとおりです。
ここに画像の説明を挿入

Module モジュール内の pom.xml 依存関係:

<repositories>
    <repository>
        <id>aliyun</id>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </repository>
    <repository>
        <id>cloudera</id>
        <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
    </repository>
    <repository>
        <id>jboss</id>
        <url>http://repository.jboss.com/nexus/content/groups/public</url>
    </repository>
</repositories>

<properties>
    <scala.version>2.12.10</scala.version>
    <scala.binary.version>2.12</scala.binary.version>
    <spark.version>3.0.0</spark.version>
    <hadoop.version>2.7.3</hadoop.version>
    <hudi.version>0.9.0</hudi.version>
    <mysql.version>5.1.48</mysql.version>
</properties>

<dependencies>
    <!-- 依赖Scala语言 -->
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}</version>
    </dependency>

    <!-- Spark Core 依赖 -->
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_${scala.binary.version}</artifactId>
        <version>${spark.version}</version>
    </dependency>
    <!-- Spark SQL 依赖 -->
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql_${scala.binary.version}</artifactId>
        <version>${spark.version}</version>
    </dependency>
    <!-- Structured Streaming + Kafka  依赖 -->
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql-kafka-0-10_${scala.binary.version}</artifactId>
        <version>${spark.version}</version>
    </dependency>

    <!-- Hadoop Client 依赖 -->
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>${hadoop.version}</version>
    </dependency>

    <!-- hudi-spark3 -->
    <dependency>
        <groupId>org.apache.hudi</groupId>
        <artifactId>hudi-spark3-bundle_2.12</artifactId>
        <version>${hudi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-avro_2.12</artifactId>
        <version>${spark.version}</version>
    </dependency>
    <!-- hudi-spark3 -->
    <dependency>
        <groupId>org.apache.hudi</groupId>
        <artifactId>hudi-hive-sync</artifactId>
        <version>${hudi.version}</version>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore</artifactId>
        <version>4.4.13</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.12</version>
    </dependency>

    <dependency>
        <groupId>org.lionsoul</groupId>
        <artifactId>ip2region</artifactId>
        <version>1.7.2</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>

</dependencies>

<build>
    <outputDirectory>target/classes</outputDirectory>
    <testOutputDirectory>target/test-classes</testOutputDirectory>
    <resources>
        <resource>
            <directory>${project.basedir}/src/main/resources</directory>
        </resource>
    </resources>
    <!-- Maven 编译的插件 -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Hudi テーブル データは HDFS ディレクトリに保存され、HDFS ファイル システム構成ファイルはモジュール モジュール リソース ディレクトリ リソースに配置されます。
ここに画像の説明を挿入

6.4.2 エンティティクラスのカプセル化

Qimo ソーシャル データ分析のカプセル化エンティティ クラス: MomoMessage、Scala 言語定義の Case Class サンプル クラスに基づいています。

package cn.itcast.hudi.momo

/**
 * 封装Momo聊天记录实体样例类CaseClass
 */
case class MomoMessage(
                         msg_time: String,
                         sender_nickyname: String,
                         sender_account: String,
                         sender_sex: String,
                         sender_ip: String,
                         sender_os: String,
                         sender_phone_type: String,
                         sender_network: String,
                         sender_gps: String,
                         receiver_nickyname: String,
                         receiver_ip: String,
                         receiver_account: String,
                         receiver_os: String,
                         receiver_phone_type: String,
                         receiver_network: String,
                         receiver_gps: String,
                         receiver_sex: String,
                         msg_type: String,
                         distance: String,
                         message: String
                      )

その後、Kafka はソーシャル データを使用し、それを解析してエンティティ クラス オブジェクトにカプセル化します。

6.4.3 ストリーミングプログラムの作成

以下に示すように、オブジェクト MomoStreamHudi を作成し、MAIN メソッドを記述し、ストリーミング プログラムを記述する 5 つの手順に従い、コード構造を書き出します。

package cn.itcast.hudi.momo

import org.apache.spark.sql._
import org.apache.spark.sql.functions._
import org.apache.spark.sql.streaming.OutputMode
import org.apache.spark.sql.types.StringType

/**
 * 编写StructuredStreaming流式程序:
实时消费Kafka中Momo聊天数据,进行转换处理,保存至Hudi表,并且自动同步至Hive表
 */
object MomoStreamHudi {
    
    
   
   def main(args: Array[String]): Unit = {
    
    
      // step1、构建SparkSession实例对象
      val spark: SparkSession = createSparkSession(this.getClass)
      
      // step2、从Kafka实时消费数据
      val kafkaStreamDF: DataFrame = readFromKafka(spark, "7mo-msg")
      
      // step3、提取数据,转换数据类型
      val streamDF: DataFrame = process(kafkaStreamDF)
      
      // step4、保存数据至Hudi表中:MOR(读取时保存)
      //printToConsole(streamDF)
      saveToHudi(streamDF)
      
      // step5、流式应用启动以后,等待终止
      spark.streams.active.foreach(
query => println(s"Query: ${query.name} is Running .............")
)
      spark.streams.awaitAnyTermination()
   }

}

6.4.3.1 SparkSession インスタンス オブジェクトの構築

Spark2.x のプログラム エントリ SparkSession から開始すると、SparkSQL バッチ処理または StructuredStreaming ストリーム コンピューティングに関係なく、プログラムは最初に SparkSession オブジェクト、カプセル化メソッド: createSparkSessionを作成します。

/**
 * 创建SparkSession会话实例对象,基本属性设置
 */
def createSparkSession(clazz: Class[_]): SparkSession = {
    
    
   SparkSession.builder()
      .appName(this.getClass.getSimpleName.stripSuffix("$"))
      .master("local[2]")
      // 设置序列化方式:Kryo
      .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
      // 设置属性:Shuffle时分区数和并行度
      .config("spark.default.parallelism", 2)
      .config("spark.sql.shuffle.partitions", 2)
          .config("spark.sql.streaming.forceDeleteTempCheckpointLocation", "true")
      .getOrCreate()
}

6.4.3.2 Kafka データの消費

カプセル化メソッド: readFromKafka、Kafka からトピック データを消費し、Kafka ブローカーの名前とアドレス情報を指定します。

/**
 * 指定Kafka Topic名称,实时消费数据
 */
def readFromKafka(spark: SparkSession, topicName: String): DataFrame = {
    
    
   spark
      .readStream
      .format("kafka")
      .option("kafka.bootstrap.servers", "node1.itcast.cn:9092")
      .option("subscribe", topicName)
      .option("startingOffsets", "latest")
      .option("maxOffsetsPerTrigger", 100000)
      .option("failOnDataLoss", "false")
      .load()
}

6.4.3.3 プリントコンソール

ストリーミング データ印刷コンソール、カプセル化メソッド: printToConsole。テストや開発プロセスでの使用に便利です。

def printToConsole(streamDF: DataFrame): Unit = {
    
    
   streamDF.writeStream
      .outputMode(OutputMode.Append())
      .queryName("query-hudi-momo")
          .format("console")
          .option("numRows", "10")
          .option("truncate", "false")
      .option("checkpointLocation", "/datas/hudi-struct-ckpt-0")
          .start()
}

6.4.3.4 データの分析と変換

Kafka 消費データの場合、まず解析してエンティティ クラス MomoMessage にカプセル化し、次にフィールドを追加して Hudi テーブルの 3 つのコア フィールド値を構築します。message_id は各データの主キーであり、日パーティションフィールドとts データ差し込みフィールド

/**
 * 对Kafka获取数据,进行转换操作,获取所有字段的值,转换为String,以便保存Hudi表
 */
def process(streamDF: DataFrame): DataFrame = {
    
    
   import streamDF.sparkSession.implicits._
   
   /*
      2021-11-25 20:52:58牛星海17870843110女156.35.36.204IOS 9.0华为 荣耀Play4T4G91.319474,29.033363成紫57.54.100.313946849234Android 6.0OPPO A11X4G84.696447,30.573691 女TEXT78.22KM有一种想见不敢见的伤痛,这一种爱还埋藏在我心中,让我对你的思念越来越浓,我却只能把你你放在我心中。
    */
   // 1-提取Message消息数据
   val messageStreamDF: DataFrame = streamDF.selectExpr("CAST(value AS STRING) message")
   
   // 2-解析数据,封装实体类
   val momoStreamDS: Dataset[MomoMessage] = messageStreamDF
      .as[String] // 转换为Dataset
      .map(message => {
    
    
         val array = message.split("\001")
         val momoMessage = MomoMessage(
            array(0), array(1), array(2), array(3), array(4), array(5), array(6), array(7), 
array(8), array(9),array(10), array(11), array(12), array(13), array(14), 
array(15), array(16), array(17), array(18), array(19)
         )
         // 返回实体类
         momoMessage
      })
   
   // 3-为Hudi表添加字段:主键id、数据聚合字段ts、分区字段day
   val hudiStreamDF = momoStreamDS.toDF()
      .withColumn("ts", unix_timestamp($"msg_time").cast(StringType))
      .withColumn(
         "message_id",
         concat($"sender_account", lit("_"), $"ts", lit("_"), $"receiver_account")
      )
      .withColumn("day", substring($"msg_time", 0, 10))
   
   hudiStreamDF
}

6.4.3.5 Hudiテーブルの保存

foreachBatch メソッドを使用して、データの各バッチをストリーム データ セット Stream DataFrame の Hudi テーブルに保存します。必要な属性フィールドを指定する必要があります。

/**
 * 将流式数据集DataFrame保存至Hudi表,分别表类型:COW和MOR
 */
def saveToHudi(streamDF: DataFrame): Unit = {
    
    
   streamDF.writeStream
      .outputMode(OutputMode.Append())
      .queryName("query-hudi-momo")
      // 针对每微批次数据保存
      .foreachBatch((batchDF: Dataset[Row], batchId: Long) => {
    
    
         println(s"============== BatchId: $batchId start ==============")
         
         import org.apache.hudi.DataSourceWriteOptions._
         import org.apache.hudi.config.HoodieWriteConfig._
         import org.apache.hudi.keygen.constant.KeyGeneratorOptions._
         
         batchDF.write
            .format("hudi")
            .mode(SaveMode.Append)
            .option(TBL_NAME.key, "7mo_msg_hudi")
            .option(TABLE_TYPE.key(), "MERGE_ON_READ")
            .option(RECORDKEY_FIELD_NAME.key(), "message_id")
            .option(PRECOMBINE_FIELD_NAME.key(), "ts")
            .option(PARTITIONPATH_FIELD_NAME.key(), "day")
            .option(HIVE_STYLE_PARTITIONING_ENABLE.key(), "true")
            // 插入数据,产生shuffle时,分区数目
            .option("hoodie.insert.shuffle.parallelism", "2")
            .option("hoodie.upsert.shuffle.parallelism", "2")
            // 表数据存储路径
            .save("/hudi-warehouse/7mo_msg_hudi")
      })
      .option("checkpointLocation", "/datas/hudi-struct-ckpt")
      .start()
}

ここまでは、ストリーミング プログラム StructuredStreaming を作成し、各コンポーネント サービスをテストのために開始しました。

6.4.4 ストリーミング プログラムの実行

ZK サービス、Kafka サービス、および HDFS サービスのサービスを開始し、次にストリーミング アプリケーションを実行し、最後に Flume エージェントとシミュレートされたデータ プログラムを実行して、Hudi テーブル データ ストレージ ディレクトリを表示します。

# NameNode和DataNode
hadoop-daemon.sh start namenode 
hadoop-daemon.sh start datanode

# ZK服务和Kafka服务
/export/server/zookeeper/bin/zkServer.sh start 
/export/server/kafka/bin/kafka-server-start.sh -daemon /export/server/kafka/config/server.properties

# Flume Agent
/export/server/flume/bin/flume-ng agent \
-c conf/ \
-n a1 \
-f /export/server/flume/conf/7mo_mem_kafka.properties \
-Dflume.root.logger=INFO,console

# 模拟数据程序
java -jar /export/data/7mo_init/7Mo_DataGen.jar \
/export/data/7mo_init/7Mo_Data.xlsx \
/export/data/7mo_data/ \
5000

Hudi ストレージ ディレクトリ構造:
ここに画像の説明を挿入
これまでのところ、Hudi テーブルへの Qimo ソーシャル データのリアルタイム ストレージ、リンク全体が完了しています。
ここに画像の説明を挿入

6.5 統合された Hive インジケーター分析

Hudi テーブル データを Hive テーブルに関連付け、beeline などのクライアントを使用して SQL を作成し、Hudi テーブル データを分析します。
ここに画像の説明を挿入

6.5.1 Hiveテーブルの作成

Hive MetaStore サービスと HiveServer2 サービスを開始してから、beeline クライアントを開始します。

/export/server/hive/bin/start-metastore.sh
/export/server/hive/bin/start-hiveserver2.sh

/export/server/hive/bin/start-beeline.sh

ここに画像の説明を挿入
DDL ステートメントを作成し、Hive テーブルを作成し、Hudi テーブルを関連付け、InputFormat 実装クラスを設定します。

# 创建Hive表,映射到Hudi表
CREATE EXTERNAL TABLE db_hudi.tbl_7mo_hudi(
  msg_time             String,
  sender_nickyname     String,
  sender_account       String,
  sender_sex           String,
  sender_ip            String,
  sender_os            String,
  sender_phone_type    String,
  sender_network       String,
  sender_gps           String,
  receiver_nickyname   String,
  receiver_ip          String,
  receiver_account     String,
  receiver_os          String,
  receiver_phone_type  String,
  receiver_network     String,
  receiver_gps         String,
  receiver_sex         String,
  msg_type             String,
  distance             String,
  message              String,
  message_id           String,
  ts                   String       
)
PARTITIONED BY (day string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.HoodieParquetInputFormat' 
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION '/hudi-warehouse/7mo_msg_hudi' ;

Hudi はパーティション テーブルであるため、パーティション情報を手動で追加する必要があります。

alter table db_hudi.tbl_7mo_hudi 
add if not exists partition(day = '2021-11-27') location '/hudi-warehouse/7mo_msg_hudi/day=2021-11-27' ;

ここに画像の説明を挿入

Hive テーブルの最初の 10 レコードをクエリします。

SELECT
  msg_time, sender_nickyname, receiver_nickyname, ts 
FROM db_hudi.tbl_7mo_hudi 
WHERE day = '2021-11-27'
limit 10 ;

ここに画像の説明を挿入

6.5.2 経営指標の分析

Qimoソーシャルデータに対して簡易インデックス統計分析を行うためのSQLを記述します データフローが少ないためローカルモードに設定して実行します。

set hive.exec.mode.local.auto=true;
set hive.mapred.mode=nonstrict;
  • 指標 1: 統計的な総メッセージ量
WITH tmp AS (
  SELECT COUNT(1) AS momo_total  FROM db_hudi.tbl_7mo_hudi WHERE day = '2021-11-27'
)
SELECT "全国" AS momo_name, momo_total FROM tmp;

ここに画像の説明を挿入

  • 指標 2: 各ユーザーの統計、送信されたメッセージの量
WITH tmp AS (
  SELECT 
    sender_nickyname, COUNT(1) momo_total 
  FROM db_hudi.tbl_7mo_hudi 
  WHERE day = '2021-11-27' GROUP BY sender_nickyname
)
SELECT 
  sender_nickyname AS momo_name, momo_total
FROM tmp 
ORDER BY momo_total DESC LIMIT 10;

ここに画像の説明を挿入

  • 指標 3: 各ユーザーの統計、受信したメッセージの量
WITH tmp AS (
  SELECT 
    receiver_nickyname, COUNT(1) momo_total 
  FROM db_hudi.tbl_7mo_hudi 
  WHERE day = '2021-11-27' GROUP BY receiver_nickyname
)
SELECT 
  receiver_nickyname AS momo_name, momo_total  
FROM tmp 
ORDER BY momo_total DESC LIMIT 10;

ここに画像の説明を挿入

  • 指標 4: 男性と女性が送信したメッセージの量に関する統計
SELECT 
  sender_sex, receiver_sex, COUNT(1) momo_total 
FROM db_hudi.tbl_7mo_hudi 
WHERE day = '2021-11-27' GROUP BY sender_sex, receiver_sex;

ここに画像の説明を挿入

6.6 Sparkオフラインインジケーター分析

SparkSQL プログラムを作成し、Hudi テーブル データをロードして DataFrame にカプセル化し、SQL を作成してビジネス指標のニーズに従ってデータを分析し、最後にそれを MySQL データベース テーブルに保存します。フロー図は次のとおりです。
ここに画像の説明を挿入

6.6.1 要件の説明

Qimo ソーシャル ニュース データのリアルタイム統計操作には、次の統計要件が必要です。

  • 1)、統計メッセージの総数
  • 2) IP アドレスに基づいて地域 (都道府県) ごとに送受信されたメッセージの数をカウントします。
  • 3) Qimo ソーシャル メッセージで各ユーザーが送受信したメッセージの数をカウントします。
    ここに画像の説明を挿入

6.6.2 データベーステーブルの作成

上記のビジネス要件と最終結果を、MySQL データベースの 1 つのテーブル 7mo.7mo_report に保存します。
ここに画像の説明を挿入

このうち、フィールド7mo_category はインジケーターのタイプを示します。

  • 1: 全国の情報量統計を示します。
  • 2: 各都道府県の情報発信量の統計を示します。
  • 3:各都道府県の情報受信量の統計を示す。
  • 4: ユーザーが送信した情報量の統計を示します。
  • 5: ユーザーが受信した情報量の統計を示します
    。 MySQL データベースで、データベース: 7mo、テーブル: 7mo_reprot を作成します。対応する DDL ステートメントは次のとおりです。
-- 创建数据库
CREATE DATABASE IF NOT EXISTS 7mo ;
-- 创建表
CREATE TABLE IF NOT EXISTS `7mo`.`7mo_report` (
    `7mo_name` varchar(100) NOT NULL,
    `7mo_total` bigint(20) NOT NULL,
    `7mo_category` varchar(100) NOT NULL,
    PRIMARY KEY (`7mo_name`, `7mo_category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;

6.6.3 指標分析プログラムの作成

オブジェクト オブジェクトを作成します: MomoSQLHudi、MAIN メソッドを記述し、ストリーミング プログラムを記述する 5 つの手順に従い、次のようにコード構造を書き出します。

package cn.itcast.hudi.momo

import org.apache.spark.sql.{
    
    DataFrame, Dataset, Row, SaveMode, SparkSession}
import org.lionsoul.ip2region.{
    
    DataBlock, DbConfig, DbSearcher}

/**
 * 编写SparkSQL程序,基于DSL和SQL分析Hudi表数据,最终保存值MySQL数据库表中
 */
object MomoSQLHudi {
    
    
   
   def main(args: Array[String]): Unit = {
    
    
      // step1、构建SparkSession实例对象
      val spark: SparkSession = createSparkSession(this.getClass)
      
      // step2、加载Hudi表数据,指定Hudi数据存储路径
      val hudiDF: DataFrame = loadHudiTable(spark, "/hudi-warehouse/7mo_msg_hudi")
      //println(s"Count = ${hudiDF.count()}")
      //hudiDF.printSchema()
      //hudiDF.show(numRows = 10, truncate = false)
      
      // step3、数据ETL转换:提取字段,解析IP为省份和城市
      val etlDF: DataFrame = etl(hudiDF)
      //println(s"Count = ${etlDF.count()}")
      //etlDF.printSchema()
      //etlDF.show(numRows = 100, truncate = false)
      
      // step4、业务指标分析
      process(etlDF)
      
      // 应用结束,关闭资源
      spark.stop()
   }
}

その中で、以前のリアルタイム ストレージと同じように、SparkSession オブジェクト、カプセル化メソッド: createSparkSessionを作成します。

6.6.3.1 Hudiテーブルデータのロード

Spark DataSource 外部データ ソース インターフェイスを使用して、Hudi テーブル データをロードし、データ ストレージ パスを指定し、メソッドloadHudiTableをカプセル化します。

/**
 * 指定Hudi表数据存储path,加载Hudi表数据,返回DataFrame
 */
def loadHudiTable(spark: SparkSession, tablePath: String): DataFrame = {
    
    
   val dataframe = spark.read
      .format("hudi")
      .load(tablePath)
   
   // 返回数据
   dataframe
}

6.6.3.2 IP アドレスを解析してフィールドを選択する

IP アドレスを [province] に解決するには、[ip2region] サードパーティ ツール ライブラリ、公式 Web サイトの URL: https://gitee.com/lionsoul/ip2region/ を使用して、IP2Region の使用を導入することをお勧めします。サードパーティのライブラリ:

  • 最初のステップでは、IP データセット [ip2region.db] をプロジェクトの下の [dataset] ディレクトリにコピーします。
    ここに画像の説明を挿入

  • 2 番目のステップでは、Maven に依存関係を追加します。

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>1.7.2</version>
</dependency>
  • 3 番目のステップである ip2region の使用では、
    ここに画像の説明を挿入
    カスタム UDF 関数メソッドが採用され、IP アドレス データが転送され、解析されて州が返されます。
    ここに画像の説明を挿入

IP アドレスを地域に解析することに加えて、ビジネス要件に関連するフィールドを選択することも必要です。カプセル化方法: etl、コードは次のとおりです。

/**
 * 提取字段数据和转换经纬度为省份城市
 */
def etl(dataframe: DataFrame): DataFrame = {
    
    
   val session: SparkSession = dataframe.sparkSession
   
   // 1-自定义UDF函数,解析IP地址为省份和城市
   session.udf.register(
      "ip_to_province",
      (ip: String) => {
    
    
         // 构建DbSearch对象
         val dbSearcher = new DbSearcher(new DbConfig(), "dataset/ip2region.db")
         
         // 依据IP地址解析
         val dataBlock: DataBlock = dbSearcher.btreeSearch(ip)
         // 中国|0|海南省|海口市|教育网
         val region: String = dataBlock.getRegion
         // 分割字符串,获取省份和城市
         val Array(_, _, province, _, _) = region.split("\\|")
         // 返回Region对象
         province
      }
   )
   
   // 2-提取字段和解析IP
   dataframe.createOrReplaceTempView("view_tmp_momo")
   val etlDF: DataFrame = session.sql(
      """
        |SELECT
        |  day, sender_nickyname, receiver_nickyname,
        |  ip_to_province(sender_ip) AS sender_province,
        |  ip_to_province(receiver_ip) AS receiver_province
        |FROM
        |  view_tmp_momo
        |""".stripMargin
   )
   
   // 返回结果数据
   etlDF
}

6.6.3.3 経営指標の分析

DataFrame を一時ビューとして登録し、分析用の SQL ステートメントを記述し、最後にすべてのインジケーターの結果をマージして保存します。

/**
 * 按照业务指标分析数据
 */
def process(dataframe: DataFrame): Unit = {
    
    
   val session: SparkSession = dataframe.sparkSession
   
   // 1-将DataFrame注册为临时视图
   dataframe.createOrReplaceTempView("view_tmp_etl")
   // 2-指标1:统计总消息量
   val reportAllTotalDF: DataFrame = session.sql(
      """
        |WITH tmp AS (
        |  SELECT COUNT(1) AS 7mo_total  FROM view_tmp_etl
        |)
        |SELECT "全国" AS 7mo_name, 7mo_total, "1" AS 7mo_category FROM tmp;
        |""".stripMargin
   )
   // 2-指标2:统计各省份发送消息量
   val reportSenderProvinceTotalDF: DataFrame = session.sql(
      """
        |WITH tmp AS (
        |  SELECT sender_province, COUNT(1) AS 7mo_total FROM view_tmp_etl GROUP BY sender_province
        |)
        |SELECT sender_province AS 7mo_name, 7mo_total, "2" AS 7mo_category FROM tmp;
        |""".stripMargin
   )
   // 2-指标3:统计各省份接收消息量
   val reportReceiverProvinceTotalDF: DataFrame = session.sql(
      """
        |WITH tmp AS (
        |  SELECT receiver_province, COUNT(1) AS 7mo_total FROM view_tmp_etl GROUP BY receiver_province
        |)
        |SELECT receiver_province AS 7mo_name, 7mo_total, "3" AS 7mo_category FROM tmp;
        |""".stripMargin
   )
   // 2-指标4:统计各个用户, 发送消息量
   val reportSenderNickyNameTotalDF: DataFrame = session.sql(
      """
        |WITH tmp AS (
        |  SELECT sender_nickyname, COUNT(1) AS 7mo_total FROM view_tmp_etl GROUP BY sender_nickyname
        |)
        |SELECT sender_nickyname AS 7mo_name, 7mo_total, "4" AS 7mo_category FROM tmp;
        |""".stripMargin
   )
   // 2-指标5:统计各个用户, 接收消息量
   val reportReceiverNickyNameTotalDF: DataFrame = session.sql(
      """
        |WITH tmp AS (
        |  SELECT receiver_nickyname, COUNT(1) AS 7mo_total FROM view_tmp_etl GROUP BY receiver_nickyname
        |)
        |SELECT receiver_nickyname AS 7mo_name, 7mo_total, "5" AS 7mo_category FROM tmp;
        |""".stripMargin
   )
   // 3-保存报表至MySQL数据库
   val reportTotalDF: Dataset[Row] = reportAllTotalDF
      .union(reportSenderProvinceTotalDF)
      .union(reportReceiverProvinceTotalDF)
      .union(reportSenderNickyNameTotalDF)
      .union(reportReceiverNickyNameTotalDF)
   // reportTotalDF.show(500, truncate = false)
   reportTotalDF
      .coalesce(1)
          .write
          .mode(SaveMode.Append)
          .format("jdbc")
          .option("driver", "com.mysql.jdbc.Driver")
          .option("url", 
"jdbc:mysql://node1.itcast.cn:3306/?useUnicode=true&characterEncoding=utf-8&useSSL=false")
          .option("dbtable", "7mo.7mo_report")
          .option("user", "root")
          .option("password", "123456")
          .save()
}

このうち、SparkSQL の外部データ ソースの JDBC メソッドは、結果を MySQL データベース テーブルに保存するために直接使用されます。

6.6.4 レポートプログラムの実行

開発が完了すると、Spark プログラムは Hudi テーブル データをロードし、ビジネス指標に従って計算し、結果を MySQL データベースに保存します。

  • MySQL データベースのテーブル データを表示する
    ここに画像の説明を挿入

  • 各指標の上位 5 データをクエリする

(SELECT 7mo_name, 7mo_total, "全国总信息量" AS "7mo.category"
FROM 7mo.7mo_report WHERE 7mo_category = 1)
UNION
(SELECT 7mo_name, 7mo_total, "省份发送信息量" AS "7mo.category"
FROM 7mo.7mo_report WHERE 7mo_category = 2 ORDER BY 7mo_total DESC LIMIT 5)
UNION
(SELECT 7mo_name, 7mo_total, "省份接收信息量" AS "7mo.category"
 FROM 7mo.7mo_report WHERE 7mo_category = 3 ORDER BY 7mo_total DESC LIMIT 5)
UNION
(SELECT 7mo_name, 7mo_total, "用户发送信息量" AS "7mo.category"
 FROM 7mo.7mo_report WHERE 7mo_category = 4 ORDER BY 7mo_total DESC LIMIT 5)
UNION
(SELECT 7mo_name, 7mo_total, "用户接收信息量" AS "7mo.category"
 FROM 7mo.7mo_report WHERE 7mo_category = 5 ORDER BY 7mo_total DESC LIMIT 5);

ここに画像の説明を挿入

6.7 FineBI レポートの視覚化

FineBI を使用してデータ MySQL データベースに接続し、ビジネス インジケーター レポート データをロードし、それをさまざまなグラフに表示します。
ここに画像の説明を挿入

6.7.1 FineBI のインストール

FineBI は、Fanruan Software Co., Ltd. が発売したビジネス インテリジェンス製品です。FineBI はセルフサービスのビッグデータ分析に位置付けられた BI ツールで、企業のビジネス担当者やデータ アナリストが問題指向の探索的分析を実行できるように支援します。公式サイト:https://www.finebi.com/
ここに画像の説明を挿入

FineBI のインストール:「FineBI Windows 版 インストールマニュアル」を参照 インストール完了後、ログインを開始し、基本画面をご確認ください。

  • ログインを開始する
    ここに画像の説明を挿入

  • コンテンツ: ホーム画面とヘルプ ドキュメント
    ここに画像の説明を挿入
    ここに画像の説明を挿入- ダッシュボード: すべてのビジュアル レポートの作成に使用されます。
    ここに画像の説明を挿入

  • データ準備: さまざまなレポートのデータ ソースを構成するために使用されます
    ここに画像の説明を挿入-管理システム: FineBI 全体の使用を管理するために使用されます: ユーザー管理、データ ソース管理、プラグイン管理、権限管理など。
    ここに画像の説明を挿入

6.7.2 データソースの構成

MySQL データベース接続を作成します: [管理システム] -> [データ接続] -> [データ接続管理]
ここに画像の説明を挿入
ここに画像の説明を挿入

MySQL データベース接続情報を入力します。

数据连接名称:node1-mysql
用户名:root
密码:123456
数据连接URL:jdbc:mysql://node1.itcast.cn:3306/7mo?useUnicode=true&characterEncoding=utf8

ここに画像の説明を挿入
ここに画像の説明を挿入

6.7.3 データセットの追加

MySQL データベースにビジネス レポートを追加します: 7mo_report、[データ準備] を選択し、グループ [Qimo Data] とビジネス パッケージ [Qimo Report] を追加します。
ここに画像の説明を挿入

[Qimo Report] をクリックしてテーブルを追加し、[SQL Data Set] メソッドを使用します。
ここに画像の説明を挿入

テーブル名とSQL文を入力してください

SELECT
  7mo_name, 7mo_total,
  CASE 7mo_category
      WHEN '1' THEN '总消息量'
      WHEN '2' THEN '各省份发送量'
      WHEN '3' THEN '各省份接收量'
      WHEN '4' THEN '各用户发送量'
      WHEN '5' THEN '各用户接收量'
  END AS 7mo_category
FROM 7mo.7mo_report 

ここに画像の説明を挿入

6.7.4 ダッシュボードの作成

まず、下の図に示すように、[Qimo Social Data Statistical Report] という名前のダッシュボードを作成します。
ここに画像の説明を挿入
次に、ダッシュボードのテンプレート スタイル [プリセット スタイル 5]: ダークブルーの海の背景を選択します。
ここに画像の説明を挿入

  • まずタイトルを追加します: [その他] -> [テキストコンポーネント]
    ここに画像の説明を挿入

ダッシュボードの名前を入力します: Qimo Social Data Statistical Report
ここに画像の説明を挿入 - 次に、メッセージの総数を表示するテキスト コンポーネントを追加します。
ここに画像の説明を挿入


ここに画像の説明を挿入
以下の図に示すように、7mo_report_mysql の前にテーブルを追加することを選択します。フィールド値を選択し、フィールド カテゴリをフィルターします。
ここに画像の説明を挿入

6.7.5 棒グラフ: メッセージを送信した上位 10 人のユーザー

最も多くのメッセージを送信した上位 10 人のユーザーが縦棒グラフで表示されます。

  • ステップ1、コンポーネントを追加し、[縦棒グラフ]を選択し、タイトル名を入力します。
    ここに画像の説明を挿入
  • ステップ 2. さまざまなフィールドを選択し、関連するフィルタリングを設定して表示します
    ここに画像の説明を挿入
    。その中で表示されるデータは、ユーザーが送信した情報量の統計データです。
    ここに画像の説明を挿入

また、Top10のみ表示する場合は発信情報量が最も多いため、フィルタリング操作が必要となります
ここに画像の説明を挿入
縦棒グラフ表示の場合は、発信情報量が多い順にソートしてください
ここに画像の説明を挿入

6.7.6 円グラフ: 情報送信量上位 10 州

上位10州の情報発信量が円グラフで表示されます 具体的な操作は以下の通りです。

  • 手順1. コンポーネントを追加し、[円グラフ]を選択し、タイトル名を入力します。
    ここに画像の説明を挿入

  • ステップ 2. さまざまなフィールドを選択し、関連するフィルタリングを設定して表示します
    ここに画像の説明を挿入
    。その中で、フィルタリングして、各州から送信された情報量の統計データを取得します
    ここに画像の説明を挿入
    。さらに、送信された情報量が最も多い上位 10 州のみが取得されます。
    ここに画像の説明を挿入

上の円グラフでは外枠にデータが表示されており、設定は以下の通りです。
ここに画像の説明を挿入

6.7.7 地図: 州別の情報量

各都道府県から発信されている情報量を地図形式で表示します 具体的な操作は以下の通りです。

  • 手順1. コンポーネントを追加し、[エリアマップ]を選択し、タイトル名を入力します。
    ここに画像の説明を挿入
  • ステップ 2: 地理的役割にマップする都道府県フィールドを選択します
    ここに画像の説明を挿入
  • ステップ 3. さまざまなフィールドを選択し、関連するフィルタリングを設定して表示します
    ここに画像の説明を挿入

その中で、各都道府県の発信情報量の統計データを取得するためのフィルターを作成します。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/toto1297488504/article/details/132257418