目录

通用语言查询系统

自然语言(语音 / 文本)→ 结构化查询条件 → MongoDB 查询
基于 Flask + MongoDB,内置学生信息管理模块


一、项目简介

本项目实现了一个 通用语言查询系统:用户用自然语言说出(或输入)一句查询诉求,例如

「我要查询性别为男,年龄小于18岁的所有学生信息」

系统会自动完成:文本清洗 → 列名识别 → 运算符识别 → 条件切分 → 多条件逻辑组合 → 生成查询语句 → 执行查询并返回结果表格

实现上做了两层设计:

  1. 通用性:条件解析不硬编码任何表结构。列名、别名、字段类型、可用运算符全部由集合元数据(COLUMN_LABELS / COLUMN_ALIASES / COLLECTION_SCHEMA 及实际抽样数据)动态推断,界面上的「集合名」可随时切换。
  2. 可解释性:解析结果同时输出中文 WHERE 展示串、英文字段 WHERE 串与最终的 MongoDB 查询文档,便于对照验证。

附带一个 学生信息管理 模块(增删改查 + 分页 + 关键词搜索 + 表单校验),作为查询的数据来源与功能对照。


二、功能模块

1. 学生信息管理

路由 方法 说明
/ GET 学生列表,分页(每页 10 条)、关键词模糊搜索(姓名 / 学号)
/add GET/POST 新增学生,表单校验
/edit/<student_id> GET/POST 编辑学生
/view/<student_id> GET 学生详情
/delete/<student_id> GET 删除学生

表单校验规则(student_crud.validate_student):

  • 学号:新增时必填且不可重复
  • 姓名:长度 2–20 个字符
  • 性别:必须为「男」或「女」
  • 年龄:15–100 之间的数字
  • 专业、班级:不能为空
  • 邮箱、手机号:选填,填写时校验格式(邮箱正则、1[3-9]\d{9} 手机号)

2. 通用语音查询

路由 方法 说明
/query GET 语音查询主界面(选择集合、语音输入、条件构造、结果表格)
/api/tables GET 返回可用集合列表
/api/columns/<table_name> GET 返回该集合的列元数据(字段名、中文标签、类型、可用运算符)
/api/operators?type= GET 按字段类型返回可用运算符
/api/parse POST 解析文本为条件行,返回条件、WHERE 展示串、MongoDB 过滤器
/api/build_where POST 根据前端条件行重新生成 WHERE 与过滤器
/api/query POST 执行查询(最多返回 500 条)
/api/speech POST 上传音频 → 百度短语音识别 → 返回文本(可选)

界面操作流程:语音/文本输入 → 解析为查询条件 → 条件行可视化编辑(列名 / 运算符 / 值 / 逻辑符)→ 生成 WHERE → 执行查询


三、核心能力说明

3.1 数据模型

集合 说明
students 学生主表:student_idnamegenderagemajorclass_nameemailphoneaddressenrollment_date
student_view students 汇总生成的宽表集合,额外包含 college_name(学院),用于模拟「多表先建视图再查询」的场景

student_view 的生成方式:遍历 students,按 MAJOR_COLLEGE_MAP(专业 → 学院)补全 college_name 后整体重建。学生数据发生增删改时,app.py 会自动调用 sync_student_view() 保持视图同步。

3.2 自然语言解析(voice_parser.py

支持的中文表达(OP_PATTERNS):

用户说法 解析运算符
大于等于 / 不少于 / 不低于 >=
小于等于 / 不大于 / 不超过 <=
大于 / 高于 / 超过 / 多于 >
小于 / 低于 / 不足 / 少于 / 未满 / 不到 <
不等于 / 不是 / 不为 !=
等于 / 为 / 是 =
包含 / 含有 / 包括 Like
为空 / 是空 Is

解析流程中的关键处理:

  • 噪声词清洗:自动剔除「我要查询」「我想查询」「请查询」「所有」「学生信息」「的信息」「的记录」等口语化冗余。
  • 无标点连读切分:语音识别结果通常没有标点,解析器会按「列名 + 为/是/比较符」的边界切分,例如 性别为男专业为计算机科学性别为男 | 专业为计算机科学
  • 中文数字转换chinese_to_arabic() 支持 二十 → 20十八 → 18,同时兼容「18岁」这类带单位的写法。
  • 性别口语归一化男生 / 男性 / 男的 → 男,并处理连读后残留的「男专业」只取单字。
  • 逻辑连接词并且 / 而且 / 以及 / 同时 / 和 / 且 解析为 and或者 / 或 解析为 or
  • 列名与别名:既认英文字段名,也认中文标签与别名(如「院系 / 学院」→ college_name,「男女」→ gender)。

3.3 查询构造(query_builder.py

  • 按类型限定运算符:数值型支持比较与 Is,文本型支持 =!=LikeIs
  • 双视图输出
    • build_where_sql(...) → 中文标签 WHERE 串,如 性别='男' and 年龄<18(用于界面展示)
    • build_where_for_execution(...) → 英文字段 WHERE 串(用于对照)
  • MongoDB 过滤器生成conditions_to_mongo_filter):
    • Like{"$regex": pattern, "$options": "i"}% 通配符转为 .*
    • IsNULL$or[{field: None}, {field: {$exists: False}}]NOT NULL{"$exists": True, "$ne": None}
    • or 逻辑合并进 $or 数组,not 逻辑转为 $and + $nor
    • 数值条件按字段类型自动转换(int / float

3.4 语音输入(speech_service.py

提供两种语音转文本方式,前端会根据配置自动选择:

  1. 浏览器 Web Speech API(默认,无需任何配置)——static/js/main.js 中直接调用,适合 Chrome / Edge。

  2. 百度短语音识别(服务端 STT,可选)——配置环境变量后启用,前端录音上传到 /api/speech,后端调用百度 vop.baidu.com/server_api 识别。需要配置:

    set BAIDU_APP_ID=你的AppID
    set BAIDU_API_KEY=你的APIKey
    set BAIDU_SECRET_KEY=你的SecretKey

    三项均配置时,界面显示绿色 百度 STT 徽标;否则显示 Web Speech API 徽标。access_token 已做内存缓存(提前 60 秒过期)。


四、技术栈

层次 技术
后端框架 Flask(Jinja2 模板 + JSON API)
数据库 MongoDB(flask-pymongo / pymongo
前端 Jinja2 模板 + Bootstrap 5.3 + Bootstrap Icons 1.11 + 原生 JavaScript
语音识别 Web Speech API(浏览器) / 百度短语音识别(服务端,可选)
运行环境 Python 3(虚拟环境 venv

五、目录结构

通用语言查询系统/
├── app.py                     # Flask 入口:路由、学生管理、查询 API
├── config.py                  # 配置:MongoDB 连接、集合名、百度语音密钥
├── database.py                # MongoDB 操作:集合元数据、示例数据、视图同步、查询执行
├── query_builder.py           # 运算符定义、WHERE 串构造、MongoDB 过滤器生成
├── voice_parser.py            # 自然语言 → 查询条件解析器
├── speech_service.py          # 百度短语音识别封装(可选)
├── student_crud.py            # 学生增删改查与表单校验
├── init_view.py               # 手动重建 student_view 集合
├── test_parser.py             # 解析器测试脚本(含无标点连读用例)
├── start.bat                  # 一键启动:拉起 MongoDB + 虚拟环境 + Flask
├── data/                      # 本地 MongoDB 数据目录(start.bat 使用 data\mongo)
├── static/
│   ├── css/
│   │   ├── style.css          # 全局样式
│   │   └── query.css          # 语音查询页样式
│   └── js/
│       └── main.js            # 语音输入、条件行 UI、API 交互
├── templates/
│   ├── base.html              # 基础布局(导航栏 + flash 消息)
│   ├── students/
│   │   ├── list.html          # 学生列表
│   │   ├── _form.html         # 表单片段
│   │   ├── add.html / edit.html
│   │   └── view.html          # 学生详情
│   └── query/
│       └── index.html         # 语音查询主界面
├── 通用语言查询系统设计文档.docx
└── 安装部署说明.pdf

六、快速开始

6.1 环境要求

依赖 版本建议
Python 3.8+
MongoDB 4.4+(本机 27017 端口)
浏览器 Chrome / Edge(使用 Web Speech API 时)

Python 依赖包:

flask
flask-pymongo
pymongo

6.2 方式一:一键启动(Windows,推荐)

双击 start.bat,脚本会依次完成:

  1. 检测 27017 端口是否已有 MongoDB 在监听;
  2. 若未监听,先尝试启动 Windows 服务 MongoDB,失败则用 C:\Program Files\MongoDB\Server\{8.0,7.0,6.0,5.0}\bin\mongod.exedata\mongo 为数据目录、127.0.0.1:27017 启动本地实例;
  3. 创建 / 激活虚拟环境 venv
  4. 安装 requirements.txt 中的依赖;
  5. 启动 Flask 应用。

注意:脚本会执行 pip install -r requirements.txt,但当前仓库中 未包含该文件。请先手动创建 requirements.txt

flask>=2.3
flask-pymongo>=2.3.0
pymongo>=4.0

6.3 方式二:手动启动

# 1. 确认 MongoDB 已启动(默认 127.0.0.1:27017)

# 2. 创建并激活虚拟环境
python -m venv venv
venv\Scripts\activate          # Windows
# source venv/bin/activate     # macOS / Linux

# 3. 安装依赖
pip install flask flask-pymongo pymongo

# 4. 启动应用
python app.py

启动成功后控制台输出:

MongoDB 连接成功:mongodb://127.0.0.1:27017/homework4_db?serverSelectionTimeoutMS=5000
==================================================
作业4 启动成功
学生管理: http://127.0.0.1:5000
语音查询: http://127.0.0.1:5000/query
==================================================

访问地址:

6.4 首次运行说明

首次启动时会自动执行 init_db()

  1. ping 检测 MongoDB 连接;
  2. students 集合为空,写入 6 条示例学生数据(张三、李四、王五、赵六、陈七、刘八);
  3. 调用 sync_student_view() 生成 student_view 宽表集合。

若视图数据与主表不一致,可手动重建:

python init_view.py

七、配置项

配置集中在 config.py,全部支持环境变量覆盖:

环境变量 默认值 说明
MONGO_DB_NAME homework4_db 数据库名
MONGO_HOST 127.0.0.1 MongoDB 主机
MONGO_PORT 27017 MongoDB 端口
MONGO_URI 由上面三项拼接 完整连接串(优先级最高)
QUERY_TABLE students 查询页默认集合
MONGO_COLLECTIONS students,student_view 集合下拉顺序
BAIDU_APP_ID / BAIDU_API_KEY / BAIDU_SECRET_KEY 百度短语音识别凭据(可选)
SECRET_KEY voice-query-dev-key Flask session 密钥

其他:Flask 监听 0.0.0.0:5000,开启 debug=True


八、使用示例

/query 页面选择集合 students,点击「语音输入」或直接在文本框输入:

输入文本 解析结果(WHERE 展示串)
我要查询性别为男,年龄小于18岁的所有学生信息 性别='男' and 年龄<18
我要查询性别为男专业为计算机科学的所有学生信息 性别='男' and 专业='计算机科学'
我要查询性别为女年龄小于二十岁的所有学生信息 性别='女' and 年龄<20
查询邮箱为空的记录 邮箱 IS NULL
姓名包含张 姓名 LIKE '%张%'

切换到 student_view 集合还可以按扩展字段查询:

输入文本 解析结果
学院为计算机学院,专业为计算机科学 学院='计算机学院' and 专业='计算机科学'

也可以运行内置测试脚本验证解析逻辑:

python test_parser.py

九、常见问题

1. 启动提示「MongoDB 连接失败」 确认本机 MongoDB 已启动(net start MongoDB,或用 start.bat 自动拉起),并检查 27017 端口是否被占用。

2. start.bat 报找不到 requirements.txt 该文件当前未随仓库提供,请按 6.2 节内容手动创建。

3. 语音输入按钮无反应 / 无法识别 浏览器 Web Speech API 需要 Chrome 或 Edge,且页面须通过 localhost / 127.0.0.1 或 HTTPS 访问。若配置了百度 STT,则走服务端识别,请确认三项环境变量均已填写。

4. 查询结果中的日期显示异常 后端统一将时间格式化为北京时间字符串(Asia/Shanghai,无 tzdata 时回退固定东八区)。数据库中 naive 时间按字面值显示,带时区的时间会转为东八区。

5. 中文乱码(Windows 控制台) start.bat 已执行 chcp 65001 并设置 PYTHONIOENCODING=utf-8,手动启动时建议同样设置。

6. 学生数据改动后视图未更新 正常路径下增删改会自动同步 student_view;若通过其他方式直接改库,请执行 python init_view.py 重建。


十、说明

  • 当前解析器面向中文口语化查询,逻辑连接词仅支持扁平的单层 and / or 组合,暂不支持括号嵌套的多层逻辑。
  • 查询结果最多返回 500 条(execute_querylimit 参数)。
  • 项目为课程实践性质,语言解析采用「规则 + 正则」实现,未引入大模型或 NLP 训练模型。
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号