一、背景与需求
在金融风控和企业合规场景中,及时获取最新的法律法规至关重要。我们的业务需要:
- 海量存储:容纳10万+法律法规条文,包括PDF/Word/HTML等多格式文档
- 高效检索:支持全文搜索、分类筛选、条文关联查询
- 实时更新:当新法规发布时,30分钟内完成入库并可供查询
- 权限控制:不同部门可见不同密级的法规内容
传统数据库方案(如MySQL)面临查询性能差、全文检索能力弱等问题,最终我们选择ElasticSearch作为核心存储引擎。
二、技术架构设计
1. 整体架构图
爬虫/API 法规数据源 数据预处理管道 ElasticSearch集群 前端应用 内部系统集成 用户 风控系统
2. 核心组件说明
组件 | 技术选型 | 职责 |
---|---|---|
数据采集层 | Python Scrapy+APIFY | 从200+政府网站抓取法规数据 |
数据处理管道 | Apache NiFi | 格式转换、元数据提取、敏感信息脱敏 |
存储引擎 | ElasticSearch | 全文检索、分类聚合、相似条文推荐 |
权限控制 | 待定 | 基于角色的访问控制(RBAC) |
前端界面 | Vue3 | 提供搜索和法规阅读界面 |
三、ElasticSearch实现细节
1. 索引设计优化
法规主索引(laws_v1)
json
PUT /laws_v1
{
"settings": {
"number_of_shards": 5,
"analysis": {
"analyzer": {
"chs_analyzer": { // 中文分词
"tokenizer": "ik_max_word",
"filter": ["synonym_filter"]
}
},
"filter": {
"synonym_filter": {
"type": "synonym",
"synonyms_path": "analysis/synonym.txt"
}
}
}
},
"mappings": {
"properties": {
"title": { "type": "text", "analyzer": "chs_analyzer" },
"content": { "type": "text", "analyzer": "chs_analyzer" },
"publish_date": { "type": "date" },
"department": { "type": "keyword" }, // 发布部门
"law_type": { "type": "keyword" }, // 法规类型
"security_level": { "type": "integer" }, // 密级
"attachments": { // 附件处理
"type": "nested",
"properties": {
"file_type": { "type": "keyword" },
"text_content": { "type": "text" }
}
}
}
}
}
特色功能实现
1. 混合内容检索(正文+附件)
json
GET /laws_v1/_search
{
"query": {
"multi_match": {
"query": "数据安全法 罚款",
"fields": ["title^3", "content", "attachments.text_content"],
"type": "cross_fields"
}
}
}
2. 时效性加权排序
json
{
"query": { ... },
"rescore": {
"window_size": 100,
"query": {
"rescore_query": {
"function_score": {
"query": { "match_all": {} },
"functions": [
{
"exp": {
"publish_date": {
"scale": "180d",
"decay": 0.5
}
}
}
]
}
}
}
}
}
2. 数据同步方案
MySQL binlog同步流程
python
# 使用Logstash JDBC插件实现准实时同步
input {
jdbc {
jdbc_driver_library => "/mysql-connector-java.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_connection_string => "jdbc:mysql://db:3306/law_db"
jdbc_user => "user"
jdbc_password => "pass"
schedule => "*/5 * * * *"
statement => "SELECT * FROM laws WHERE update_time > :sql_last_value"
use_column_value => true
tracking_column => "update_time"
}
}
output {
elasticsearch {
hosts => ["es01:9200"]
index => "laws_v1"
document_id => "%{id}"
}
}
3. 权限控制实现
目前我们集团内部整理的法律法规所有内网用户都可以查阅,没有任何限制。
不过我们计划把法规的衍生对象,也就是法律变更也保存到ES中提供给法规影响的业务方进行查阅,这一部分将会需要权限控制。
目前有两种解决方案,
一是采用OpenSearch Security插件进行控制。
二是采用传统的权限管理系统结合查询语句进行控制
个人倾向于使用第二种方案。
四、性能优化成果
1. 查询效率对比
查询类型 | MySQL方案 | ES优化方案 |
---|---|---|
简单标题检索(100万条) | 2.1s | 120ms |
复杂全文检索+过滤 | 15s+ | 800ms |
关联条文推荐 | 不支持 | 300ms |
2. 系统吞吐量
- 峰值QPS: 1,200+(10节点集群)
- 数据延迟: <1分钟(从源站更新到可检索)
- 存储成本: 原始PDF 1TB → 压缩后ES索引 120GB
五、踩坑经验总结
-
中文分词陷阱
- 错误做法:直接使用默认standard analyzer
- 正确方案:组合IK分词器+同义词库
json"analyzer": { "chs_analyzer": { "tokenizer": "ik_smart", "filter": ["synonym", "trim"] } }
-
嵌套对象性能问题
- 深层嵌套导致查询性能下降50%+
- 解决方案:
- 扁平化处理(如
attachment_filetype
) - 限制嵌套层级≤3
- 扁平化处理(如
-
权限控制误区
- 初期在应用层做过滤,导致信息泄露风险
- 最终采用OpenSearch Security的document-level security
六、未来优化方向
-
向量搜索升级
使用ES 8.x的
dense_vector
字段实现语义搜索:json"properties": { "title_vector": { "type": "dense_vector", "dims": 768, "index": true, "similarity": "cosine" } }
-
多租户支持
通过
index_per_tem
模式隔离不同客户数据。 -
冷数据归档
将5年前法规迁移到对象存储,通过ES的searchable snapshots功能保留检索能力。
通过这套方案,我们实现了法律法规信息的秒级检索,日均查询量突破50万次。欢迎在评论区交流你的ES应用场景!