11 KiB
用户学情数据导出 — 数据表与业务逻辑
整理日期:2026-06-03 | 基于
export-user-data技能 v1.5
一、数据源总览
该技能跨 4 个数据源(ES + PostgreSQL + 2 个 MySQL 库),共涉及 17+ 张表/索引:
| 序号 | 数据源 | 库/索引 | 表名 | 用途 |
|---|---|---|---|---|
| 1 | ES Online | user-audio |
— | 用户全部音频数据 |
| 2 | ES Online | llm_asr_log |
— | ASR 识别结果回填(按 makee_id 关联) |
| 3 | PG Online | vala |
user_component_play_record_0 ~ user_component_play_record_7 |
互动组件学习记录(8 张分表) |
| 4 | PG Online | vala |
user_unit_review_question_result |
课程巩固记录 |
| 5 | PG Online | vala |
user_unit_challenge_question_result |
单元挑战记录 |
| 6 | PG Online | vala |
user_unit_summary_km_result |
单元总结记录 |
| 7 | MySQL Test | vala_test |
vala_game_info |
story_id → unit_id 映射表 |
| 8 | MySQL Test | vala_test |
vala_game_chapter |
chapter_id → lesson_id 映射表 |
| 9 | MySQL Test | vala_test |
middle_interaction_component |
中互动组件配置(mid_* 类型) |
| 10 | MySQL Test | vala_test |
core_interaction_component |
核心互动组件配置(core_* 类型) |
| 11 | MySQL Online | vala_user |
vala_app_character |
账户 ID → 角色 ID 映射 |
二、各数据源详细说明
2.1 ES user-audio 索引 — 全部音频数据
查询条件: userId == 目标角色ID,最多返回 10000 条,按时间倒序排列。
输出字段:
| 字段 | 说明 |
|---|---|
userId |
角色 ID |
userMsg |
用户消息(ASR 识别结果或原始 JSON) |
userName |
用户名 |
soeData |
语音评测数据 |
audioUrl |
音频文件地址 |
asrStatus |
ASR 识别状态 |
componentId |
关联的组件 ID |
componentType |
组件类型 |
dataVersion |
数据版本号 |
timeStr |
时间字符串 |
source |
数据来源(仅当命中 makee_id 回填时有值) |
特殊逻辑(v1.2 — makee_id 回填):
当 userMsg 字段内容包含 makee_id 时:
- 从
userMsg中提取makee_id的值(支持 JSON 解析 + 正则兜底) - 用
makee_id去 ESllm_asr_log索引查询对应记录 - 将查询到的
result_text回填到userMsg字段 - 将
source字段输出到source列
如果 userMsg 不包含 makee_id,保持原始逻辑不变。
2.2 PG user_component_play_record_0~7 — 互动组件学习记录
表结构: 8 张分表,需 UNION ALL 合并查询。
查询条件: user_id == 目标角色ID,按 updated_at 倒序。
输出字段:
| 字段 | 来源 | 说明 |
|---|---|---|
user_id |
PG 原始字段 | 角色 ID |
component_unique_code |
PG 原始字段 | 组件唯一标识 |
session_id |
PG 原始字段 | 会话 ID |
c_type |
PG 原始字段 | 组件类型编码(如 mid_vocab_item) |
c_id |
PG 原始字段 | 组件 ID |
互动组件名称 |
MySQL 映射 | 根据 c_type 查组件配置表映射 |
组件标题 |
MySQL 映射 | 组件配置中的 title |
组件配置摘要 |
MySQL 映射 | mid 取 question,core 取 taskInfo |
知识点 |
MySQL 映射 | 组件配置中的 kp_relation_info |
play_result |
PG 原始字段 | 答题结果(Perfect/Good/Failed/Pass/Oops) |
user_behavior_info |
PG 原始字段 | 用户行为信息 JSON |
updated_at |
PG 原始字段 | 更新时间 |
组件名称映射规则(v1.5)
中互动组件(c_type 以 mid_ 开头)→ 查 middle_interaction_component 表:
| c_type | 互动组件名称 |
|---|---|
mid_vocab_item |
物品互动 |
mid_vocab_image |
图片互动 |
mid_vocab_fillBlank |
填词互动 |
mid_vocab_instruction |
指令互动 |
mid_sentence_dialogue + mode=express |
对话互动-表达 |
mid_sentence_dialogue + mode=read |
对话互动-朗读 |
mid_sentence_voice |
语音互动 |
mid_sentence_material |
材料互动 |
mid_sentence_makeSentence |
造句互动 |
mid_grammar_cloze |
挖空互动 |
mid_grammar_sentence |
组句互动 |
mid_pron_pron |
发音互动 |
核心互动组件(c_type 以 core_ 开头)→ 查 core_interaction_component 表:
| c_type | 互动组件名称 |
|---|---|
core_speaking_reply |
口语快答 |
core_speaking_inquiry |
口语妙问 |
core_speaking_explore |
口语探讨 |
core_speaking_monologue |
口语独白 |
core_reading_order |
合作阅读 |
core_listening_order |
合作听力 |
core_writing_imgMakeSentence |
看图组句 |
core_writing_imgWrite |
看图撰写 |
core_writing_questionMakeSentence |
问题组句 |
core_writing_questionWrite |
问题撰写 |
组件配置摘要取值规则:
mid_*:取component_config中的question字段core_*:取component_config中的taskInfo字段
知识点取值: 直接取 kp_relation_info 字段(JSON 数组格式,每个元素含 kpId、kpType、kpTitle、kpSkill、kpSkillName)
2.3 PG user_unit_review_question_result — 课程巩固记录
查询条件: user_id == 目标角色ID,按 updated_at 倒序。
输出字段:
| 字段 | 来源 | 说明 |
|---|---|---|
user_id |
PG 原始字段 | 角色 ID |
unit_id |
story_id 映射 | 通过 vala_game_info 表将 story_id 映射为 unit_id |
lesson_id |
chapter_id 映射 | 通过 vala_game_chapter 表将 chapter_id 映射为 lesson_id |
question_list |
PG 原始字段 | 题目列表 JSON |
正确率 |
计算字段 | isRight==true 的数量 / 总题数 × 100% |
updated_at |
PG 原始字段 | 更新时间 |
正确率计算逻辑: 解析 question_list JSON 数组,统计其中 isRight == true 的题目数,除以总题数,结果以百分比展示。
2.4 PG user_unit_challenge_question_result — 单元挑战记录
查询条件: user_id == 目标角色ID,按 updated_at 倒序。
输出字段:
| 字段 | 来源 | 说明 |
|---|---|---|
user_id |
PG 原始字段 | 角色 ID |
unit_id |
story_id 映射 | 通过 vala_game_info 表映射 |
category |
PG 原始字段 | 挑战类别 |
score_text |
PG 原始字段 | 得分文本 |
question_list |
PG 原始字段 | 题目列表 JSON |
updated_at |
PG 原始字段 | 更新时间 |
2.5 PG user_unit_summary_km_result — 单元总结记录
查询条件: user_id == 目标角色ID,按 updated_at 倒序。
输出字段:
| 字段 | 来源 | 说明 |
|---|---|---|
id |
PG 原始字段 | 记录 ID |
user_id |
PG 原始字段 | 角色 ID |
unit_id |
story_id 映射 | 通过 vala_game_info 表映射 |
updated_at |
PG 原始字段 | 更新时间 |
km_id |
PG 原始字段 | 知识点 ID |
km_type |
PG 原始字段 | 知识点类型 |
play_time_seconds |
计算字段 | 播放时长(原始毫秒值 ÷ 1000) |
2.6 MySQL 映射表
vala_game_info — story_id → unit_id 映射
查询逻辑: SELECT id, story_id FROM vala_game_info ORDER BY season_package_id ASC, index ASC
映射规则: 查询结果按排序后的索引位置(从 1 开始)作为 unit_id。
vala_game_chapter — chapter_id → lesson_id 映射
查询逻辑: SELECT id, chapter_id, index FROM vala_game_chapter
映射规则: chapter.index 字段值即为 lesson_id。
vala_app_character — 账户 ID → 角色 ID 映射
查询逻辑: SELECT id FROM vala_app_character WHERE account_id = <账户ID>
使用场景: 当使用 --account-ids 模式时,先查此表获取该账户下所有角色 ID,再逐个导出。
三、Excel 输出结构(8 个 Sheet)
| Sheet 序号 | Sheet 名称 | 数据来源 |
|---|---|---|
| 1 | 全部音频数据 | ES user-audio 索引 |
| 2 | 互动组件学习记录 | PG 8 张分表 + MySQL 组件配置 |
| 3 | 课程巩固记录 | PG user_unit_review_question_result |
| 4 | 单元挑战记录 | PG user_unit_challenge_question_result |
| 5 | 单元总结记录 | PG user_unit_summary_km_result |
| 6 | 统计-互动组件通过情况 | 基于 Sheet 2 聚合,按组件名称统计 Perfect/Good/Failed/Pass/Oops 数量及比例 |
| 7 | 统计-知识点通过情况 | 基于 Sheet 2 聚合,按知识点(kpId + kpType + kpTitle)统计通过情况 |
| 8 | 统计-单元总结时长 | 基于 Sheet 5 聚合,按 unit_id 累加 play_time_seconds,并转换为分钟(取整) |
四、执行方式
脚本位置
- Wrapper 脚本:
scripts/export_user_data.sh - 核心 Python 脚本:
git_repos/llm_offline_production/config_user_data_extract_and_analyze/export_user_id_data.py
命令参数
# 单角色导出
./scripts/export_user_data.sh --user-id 33123
# 多角色批量导出
./scripts/export_user_data.sh --user-ids 33123,33124,33125
# 按账户批量导出(自动查该账户下所有角色)
./scripts/export_user_data.sh --account-ids 2148,2149
# 指定输出目录
./scripts/export_user_data.sh --user-id 33123 --output-dir /tmp/my_output/
三种模式(--user-id / --user-ids / --account-ids)互斥,只能传一种。
输出文件命名
- 角色模式:
角色id_{ID}_导出时间_{YYYYMMDD}.xlsx - 账户模式:
账户id_{账户ID}_角色id_{角色ID}_导出时间_{YYYYMMDD}.xlsx
Python 依赖
python3, pymysql, psycopg2, pandas, openpyxl, requests
五、所需环境变量
| 环境变量 | 对应数据源 | 说明 |
|---|---|---|
ES_HOST |
ES Online | Elasticsearch 地址 |
ES_PORT |
ES Online | ES 端口(9200) |
ES_SCHEME |
ES Online | 协议(https) |
ES_USER |
ES Online | ES 用户名 |
ES_PASSWORD |
ES Online | ES 密码 |
PG_DB_HOST |
PG Online | PostgreSQL 地址 |
PG_DB_PORT |
PG Online | PG 端口(28591) |
PG_DB_USER |
PG Online | PG 用户名 |
PG_DB_PASSWORD |
PG Online | PG 密码 |
PG_DB_DATABASE |
PG Online | PG 数据库名(vala) |
MYSQL_HOST |
MySQL Test | MySQL 测试库地址 |
MYSQL_PORT |
MySQL Test | MySQL 测试库端口(25413) |
MYSQL_USERNAME |
MySQL Test | MySQL 测试库用户名 |
MYSQL_PASSWORD |
MySQL Test | MySQL 测试库密码 |
MYSQL_HOST_online |
MySQL Online | MySQL 线上库地址 |
MYSQL_PORT_online |
MySQL Online | MySQL 线上库端口(27751) |
MYSQL_USERNAME_online |
MySQL Online | MySQL 线上库用户名 |
MYSQL_PASSWORD_online |
MySQL Online | MySQL 线上库密码 |
凭证具体值见
secrets.md,wrapper 脚本export_user_data.sh已内置默认值。
六、注意事项
- 所有数据库连接均为只读账号,不会产生写操作
- ES 查询使用 HTTPS + 自签证书,脚本已处理
verify=False - PG 返回的
updated_at带时区信息,脚本会自动去除时区避免 Excel 写入报错 play_result支持两种格式:纯字符串("Perfect")或 JSON({"result": "Perfect"})- 导出大批量角色时建议分批执行,避免单次耗时过长
- 脚本默认输出到
output/目录