上线前必须评审文档模型,否则金仓迁移将引发聚合不准、索引失效、字段丢失三重问题;需控制json嵌套≤4层、数组类型统一、验证json_typeof()、objectid转text/uuid;禁用$facet/$lookup等不支持stage,改用join和explain;中文索引须用gin+to_tsvector('chinese'),建jsonb_path_ops索引;驱动层mongoclientoptions在金仓抛unsupportedoperationexception,压测才暴露。

上线前不评审文档模型,等于把数据结构风险直接留给生产流量——尤其是当后续要迁向金仓这类国产文档数据库时,模型设计缺陷会放大成聚合不准、索引失效、字段丢失三重问题。
JSON嵌套深度与字段类型混用是否超出金仓解析边界
金仓数据库虽支持BSON格式,但对嵌套层级和混合类型数组(如[123, "high", true])的语义还原存在隐性限制。MongoDB允许任意深度嵌套和动态类型,而金仓在写入时可能做隐式类型归一(如将true转为1),或在超过5层嵌套后丢弃深层路径。
- 检查所有
user.profile.tags类路径字段,确认嵌套不超过4层; - 禁止在同个数组中混用数字、字符串、布尔值——改用统一字符串+业务编码(如
["123", "high", "true"]); - 用
json_typeof()函数在金仓测试库中验证字段类型是否与MongoDB一致; - 特别注意
ObjectId字段:金仓不原生识别该类型,需提前转为TEXT或UUID并建立映射表。
聚合管道(Aggregation Pipeline)是否含金仓不支持的stage或表达式
金仓文档能力对$facet、$lookup、$graphLookup等stage的支持程度不一,且$group在大数据量下存在中间态缓存截断问题。错误日志中出现CommandNotSupported或结果数量不一致,基本可定位到此处。
- 逐条检查pipeline中是否含
$merge、$out、$planCacheStats等金仓明确不支持的stage; - 将
$lookup替换为显式JOIN(如SELECT ... FROM users u JOIN profiles p ON u._id = p.user_id),避免关联逻辑黑盒化; - 用
EXPLAIN命令在金仓中执行等价SQL,确认执行计划是否走索引而非全表扫描; - 对含
$unwind的管道,确保被展开字段非空——金仓遇到null数组会跳过整条文档,而MongoDB默认保留。
索引定义是否覆盖实际查询路径且符合中文语境召回要求
金仓的text索引在中文分词逻辑上与MongoDB不同,默认不启用IK或结巴分词,仅按字切分。若业务依赖{"$text": {"$search": "电子证照"}},很可能查不到“电子”“证照”分开存储的文档。
- 禁用
db.collection.createIndex({field: "text"})写法,改用金仓专用语法CREATE INDEX idx_name ON table USING gin (to_tsvector('chinese', field)); - 对高频路径查询(如
user.profile.tags),必须建jsonb_path_ops索引而非普通B-tree; - 用
SELECT * FROM table WHERE json_extract_path_text(data, 'user', 'profile', 'tags') @> '["vip"]'替代find({"user.profile.tags": "vip"}),确保语义等价; - 在测试环境用真实数据集跑
EXPLAIN ANALYZE,确认Bitmap Heap Scan占比低于10%,否则说明索引未生效。
最易被忽略的是驱动层行为差异:Spring Boot里MongoClientOptions.builder().addCommandListener()在金仓上直接抛UnsupportedOperationException,监控链路会静默中断——这不会在功能测试中暴露,只有压测时才显现。











