项目复盘 · 2019
内部工具与项目记忆:数据能力如何留给下一位使用者
一套以公司为核心的数据消费工具,以及历史清单、文档、知识产权和人员事项所暴露的组织记忆问题。
数据团队积累了很多数据库和接口,并不代表研究者能够顺利使用它们。数据源名称、字段含义、查询语法和权限分散在不同文档里,研究者常常需要先找到维护者,才能知道某项数据是否可用。
内部工具项目试图把这些能力放进统一入口;与此同时,历史项目、常用资料、知识产权和招聘等 Jira 项目则记录了另一面:如果成果归档、责任和项目关闭机制不完整,组织记忆仍会随着人员和系统变化而流失。
以公司为中心连接数据行为
内部工具的核心目标是满足研究团队的数据消费需求,并提高日常工作效率。产品规划以“公司”为统一实体,把数据查询、详情、来源明细和后续整理串成两条支线:一条面向数据采集与整理,另一条面向研究者检索和使用。
这一方向承接了公司大表项目。用户不需要分别理解每个来源的表结构,而是先搜索公司,再查看投融资、专利、法律文书等来源信息。顶部主搜索框保留搜索记忆,筛选器进一步缩小对象范围。
Jira 中已完成标签整理、智能扩展上线和顶部搜索框。标签整理覆盖了上千个主题词,为输入扩展提供基础。但标签数量本身不代表质量,仍需处理同义词、层级冲突、过期概念和错误关联,并记录每次版本变化对搜索结果的影响。
代码进一步揭示了“智能扩展”怎样工作。英文输入先查询百科重定向得到标准标题,再收集重定向同义词并翻译成中文,最后与内部标签表匹配;中文输入则直接进入标签判断。另一条接口从标签表取中文扩展词,再通过映射补充英文词。它不是端到端语义模型,而是一条“标准名—同义词—翻译—受控标签”的可解释流水线,优势是每一步都能人工检查,弱点是外部百科、翻译和本地映射任一环节失效都会造成召回下降。原实现多处捕获异常后返回 null,也会把依赖失败伪装成“没有扩展结果”。
高级筛选并非简单关键词搜索。请求把每个字段编码为一组带 type 与 value 的条件,代码再翻译成 Elasticsearch 布尔查询,支持包含、不包含、时间相等和时间区间等操作。公司字段与融资字段会被拆分:先在公司大表得到候选公司名,再以名称集合约束融资轮次索引。这种两阶段查询解决了跨索引筛选,却把实体连接压在名称上;重名、旧名和名称变更都可能造成误连或漏连,稳定公司 ID 应当贯穿两个索引。
下面是依据巨型公司控制器整理的等价伪代码。它保留“先公司、后事件”的核心逻辑,并把历史名称连接改写为重建时应使用的稳定标识。
等价伪代码
company_query = bool_query()
for field, conditions in request.company_filters:
for condition in conditions:
company_query.add(compile_condition(field, condition.type, condition.value))
companies = company_index.search(company_query, fields=["entity_id", "name"])
entity_ids = unique(companies.entity_id)
event_query = bool_query().filter(terms("entity_id", entity_ids))
for field, conditions in request.event_filters:
for condition in conditions:
event_query.add(compile_condition(field, condition.type, condition.value))
events = event_index.search(event_query, page=request.page)
return attach_company_summary(events, companies)列表排序也编码了研究偏好:上市属性优先,其次是一年内最近融资额、一年前融资额,最后按成立时间升序。返回字段再按境外公司源、合并源、工商源的顺序选择名称、地址、简介等展示值,同时直接使用统一文档上的标签。换言之,页面看似一张公司卡片,背后其实包含来源优先级和排序规则;这些规则若不版本化,同一个筛选条件在不同月份可能得到不同顺序,却无法解释原因。
“我的数据集”意味着从查看走向加工
1.2 版本计划加入“我的数据集”,让研究者把查询结果保存为可继续使用的集合。这个功能如果形成闭环,可以连接筛选、人工订正、导出和报告制作,使内部工具不再只是数据库浏览器。
但它也引入新的治理问题:数据集是静态快照还是自动更新查询,成员能否协作,来源记录改变后如何提示,导出是否包含敏感字段,删除数据集是否影响原始数据。历史事项只确认了需求与原型,“我的数据集”、1.2 开发和筛选优化仍为待办,不能认定完整实现。
文档比接口列表更接近产品
Confluence 的内部工具空间保存产品规划、需求、原型、数据、设计、接口、会议纪要、版本进度和两版 API 文档。这种结构比单一接口说明更完整,因为它同时回答“为什么做、用户怎样用、数据从哪里来、当前做到哪一步”。
GitLab 中的前端仓库有 36 次提交,持续更新到 2020 年;一个 Java 内部接口仓库有 8 次提交,保存公司筛选、融资查询、分页详情和按来源加载的结构。两者能够证明部分工具继续演进,但仓库名称、时间和文档版本无法完全绑定,不能确定每项 1.2 需求都进入了这些代码。
Java 接口同时暴露公司列表、公司总数、融资列表与总数、并购列表与总数、关键词匹配、按来源详情和异步导出。分页列表只取展示所需字段,而导出走单独文件流程,说明交互查询和批量消费已经被区分。但控制器把请求解析、查询构造、来源合并、展示字段选择和错误处理集中在一个超长类中,并使用旧式 Elasticsearch Transport Client;这使筛选语义很难单测,也让搜索引擎升级与业务规则修改互相牵连。重建时应把条件 DSL、实体连接、来源裁决、排序和响应映射拆成独立组件。
历史项目清单本身没有完成
HIS 项目只有两条待办:历史项目清单和已出品报告。它们恰好指向最重要的组织资产,却没有完成记录。DOC 项目也只有一条测试待办,两个零工单项目则仅保留项目壳。
这意味着当时的知识管理仍依赖 Confluence 空间、周报、个人交接和文件目录。资料很多,但缺少统一索引将项目、需求、文档、代码、数据集和最终交付物连接起来。当前复盘必须跨三个系统重新匹配,正是这一缺口的直接后果。
知识产权与招聘属于治理记录,不是产品成果
知识产权项目保存了软件著作权和专利两条开放事项,没有完成或申请结果证据。它们只能证明相关工作被提出,不能表述为已经获得登记或授权。
招聘项目有四条开放记录,其中包含候选人信息。此类内容与项目技术总结无关,也涉及个人隐私,因此公开文章只保留匿名数量和状态,不引用姓名、履历、评价或联系方式。历史系统中的招聘和人员资料应采用更严格的访问、保留与删除规则,而不应长期混在普通项目库中。
项目留下的经验
- 内部数据工具应围绕稳定业务实体组织来源,而不是把数据库表原样暴露给研究者。
- 保存数据集前必须定义快照、自动更新、权限、来源变更和删除语义。
- 标签与智能扩展需要版本、评测和人工订正机制,词条数量不能替代搜索质量。
- 跨公司与融资索引的过滤必须使用稳定实体 ID;名称集合只能作为兼容方案,并应记录重名与别名命中。
- 搜索排序和来源优先级本身就是产品规则,应进入配置、版本和回归样例,不能埋在控制器分支里。
- 外部百科与翻译参与查询扩展时,要区分“确实无结果”和“依赖调用失败”,并为每一步保留可观测状态。
- 项目归档应连接 Jira、Confluence、代码仓库、数据集和最终交付物,并标明责任与证据状态。
- 开放或待办的知识产权事项不能写成已申请或已授权成果。
- 招聘与人员评价应从普通项目知识库中隔离,并限制保留期限与公开范围。
证据边界
TOOL 项目有 6 条事项,其中 3 条完成、3 条待办;Confluence 的 WZTool 空间有 15 条内容记录,另有独立投融资工具页面。前端仓库有 36 次提交,内部接口仓库有 8 次提交。本文进一步核对了公司查询控制器、标签服务与导出入口,足以确认部分查询、扩展、排序和数据消费能力被实施。
HIS 的 2 条历史归档事项、DOC 的 1 条测试事项和 IP 的 2 条知识产权事项均无完成记录;RECRUIT 有 4 条开放记录。DEV 与 REPORTDATA 两个 Jira 项目没有工单。本文把这些项目保留在覆盖范围内,但不从项目名称推断不存在的成果,也不公开招聘记录中的任何个人信息。