MongoDB 作为全球主流的文档数据库,++已广泛应用于内容管理、日志分析、物联网、用户画像等业务场景,++ 在国内存量应用规模庞大,其国产化升级的核心痛点集中在兼容性------ 国产文档数据库能否支撑存量业务 "不改代码、不换习惯、平滑迁移",是衡量替代可行性的核心标准。
达梦文档数据库(DMDDB)是达梦数据自主研发的++单机++ 分布式++一体++ 文档数据库,采用++类++ JSON 文档模型存储管理数据,从++系统架构、++协议层、数据模型、核心 API 到工具生态全面对齐 MongoDB 能力。
本文基于实测验证,从通信协议、架构、数据模型、集合操作、运算符体系、聚合框架、索引能力、事务特性、高级特性、工具生态、运维安全等全链路维度,深度解析 DMDDB 的 MongoDB 兼容能力,为企业选型与业务迁移提供客观参考。
一、兼容性总览:全链路能力覆盖
|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|
| 兼容维度 | 对应的 MongoDB 能力 | DMDDB 表现 |
| 通信协议 | wire protocol、BSON、端口握手、认证握手 | 协议级兼容,mongosh 直连 |
| 数据类型 | BSON 16 类类型、动态 Schema、Schema 验证 | 支持 |
| 集合 API 操作(CRUD + 集合管理 + 统计) | insertOne、insertMany、find、findOne、distinct、countDocuments、updateOne、updateMany、replaceOne、findOneAndUpdate、findOneAndReplace、deleteOne、deleteMany、findOneAndDelete、bulkWrite、estimatedDocumentCount、createCollection、drop、dropDatabase等 | 支持 |
| 查询运算符 | 比较/逻辑/元素/数组/地理/位运算/投影 | 支持 |
| 更新运算符 | 字段/数组更新运算符 | 支持 |
| 聚合框架 | 43 个管道阶段 + 100+聚合管道运算符 | 支持 |
| 索引 | 单字段/复合/多键/文本/地理/TTL/唯一/部分/稀疏/通配符/隐藏 | 支持 |
| 多文档事务 | ACID、快照隔离级别(支持大事务) | 支持 |
| GridFS | 大文件存储 (支持 20GB+ 超大文件) | 支持 |
| Change Stream | Change Stream、changeStreamPreAndPostImages | 支持 |
| 备份恢复 | mongodump/restore、ddb_br | 支持 |
| 数据迁移 | mongodump/restore/mongoexport/mongoimport/ddb_importer、mongoshake、DMDIS | 支持 |
| 工具生态 | Studio 3T / Navicat For MongoDB / NosqlBooster for MongoDB /Compass等 | 支持 |
| 驱动/框架 | Java/GO/Node/Python/C/C++ + Spring Data等 | 支持 |
| 运维 | explain、慢日志、serverStatus、dbStats/collStats、审计日志、currentOp / killOp | 支持 |
| 安全 | SCRAM-SHA-256/SCRAM-SHA-1认证、SM4/AES存储加密、TLS加密传输 | 支持 |
| 高可用 | 支持集群部署,多engine连接,出现单节点故障不丢失数据 | 支持 |
| DMDDB Manager | 图形化管理、监控、备份、迁移、生命周期管理 | 支持 |
在"应用层日常使用"的绝大多数能力上,DMDDB 与 MongoDB 高度对齐:协议、数据类型、CRUD、运算符、聚合、索引、事务、客户端、驱动、运维命令都在兼容范围内。对绝大多数 MongoDB 应用,迁移成本集中在"改连接串"这一件事上。
下面针对每个能力都给可直接执行的命令和验证结果(截图见各小节)。
二、协议与连接兼容:wire protocol 与 BSON 对齐
兼容性的第一道门槛是通信协议。DMDDB 在协议层对齐 MongoDB wire protocol 与 BSON 编码,做到协议级兼容 MongoDB:基于该协议实现的客户端、驱动、中间件无需适配即可通信,存量应用基本不用改代码就能从 MongoDB 迁过来。
使用官方交互式 Shell mongosh 即可直接连接 DMDDB(默认端口 27017),执行 use、insert、find 等标准命令,行为与连接原生 MongoDB 一致,如下图所示。

图 2-1 mongosh 直连 DMDDB
三、架构兼容:单机、主备与分布式

图 3-1 DMDDB 分布式集群架构
- DDBMetaService:元数据服务(库/集合/用户/角色等元信息)
- DDBStoreService:文档存储服务(文档的落盘与读取)
- DDBEngineService:查询引擎服务(查询解析、执行、聚合计算)
- 部署形态:单机、集群等,按需选择,均支持脚本服务进行部署,下图。
上图为DMDDB分布式集群架构图,也支持单机形态部署,均支持服务脚本进行自动部署

图 3-2 服务化部署
DMDDB 采用单机分布式一体架构,提供单机、主备、分布式三种部署形态,分别承接 MongoDB 单机(Standalone)、复制集(Replica Set)、分片集群(Sharded Cluster)的业务场景,应用使用标准 MongoDB 连接串即可接入。
3.1 单机形态(对应 MongoDB 单机部署)
- 单进程单节点部署,适用开发测试与中小规模业务场景
- 通过服务脚本一键部署,应用以标准连接串直连,无需任何适配
- 业务增长后可升级为主备或集群形态,无需更换驱动、修改连接方式
3.2 主备形态(对应 MongoDB 复制集)
- 支持一主多备部署,主备间数据实时同步,主节点故障时自动切换,保障服务高可用与数据安全
- 应用连接串配置多个节点地址,驱动在切换后自动重连新主,业务侧无需人工干预
3.3 分布式形态(对应 MongoDB 分片集群)
- 集群由 DDBEngineService(查询服务)、DDBMetaService(元数据服务)与 DDBStoreService(存储服务)组成,对外提供与 MongoDB 分片集群等价的透明分片语义
- 数据自动分布与负载均衡,无需用户指定分片键,支持在线扩容与弹性伸缩,业务代码无需感知数据分布
四、数据模型与 BSON 类型兼容
文档数据库的两大特点是 schema 灵活、类型丰富。DMDDB 支持 MongoDB 完整的 BSON 类型体系和动态建模能力。
db.typesCollection.insertOne**({** value**:** "Hello DMDDB" });
db.typesCollection.insertOne**({** value**:** NumberInt**(** 42**)** });
db.typesCollection.insertOne**({** value**:** NumberLong**(** "9223372036854775807") });
db.typesCollection.insertOne**({** value**:** 3.14159 });
db.typesCollection.insertOne**({** value**:** NumberDecimal**(** "123.456") });
db.typesCollection.insertOne**({** value**:** true });
db.typesCollection.insertOne**({** value**:** new Date**(** "2026-08-24T10:00:00Z") });
db.typesCollection.insertOne**({** value**:** new Timestamp**(** 1**,** 2**)** });
db.typesCollection.insertOne**({** value**:** new ObjectId**()** });
db.typesCollection.insertOne**({** value**:** new BinData**(** 0**,** "SGVsbG8gV29ybGQ=") });
db.typesCollection.insertOne**({** value**:** ** "apple"**,** "banana"**,** 42**,** true** });
db.typesCollection.insertOne**({** value**:** { name**:** "John", age**:** 30**,** active**:** false } });
db.typesCollection.insertOne**({** value**:** new RegExp**(** "^hello", "i") });
db.typesCollection.insertOne**({** value**:** new Code**(** "function() { return this.name; }") });
db.typesCollection.insertOne**({** value**:** null });
db.typesCollection.insertOne**({** value**:** new MinKey**()** });
db.typesCollection.insertOne**({** value**:** new MaxKey**()** });

4 .1 核心建模特性
- 嵌套文档:文档内嵌子文档,无需 JOIN 即可表达关联(适合聚合性强的业务实体)
- 数组字段:支持数组及数组内嵌文档,并有专属数组操作符
- 动态 Schema:同一集合各文档字段可不同,无需 DDL 即可新增字段
- Schema 验证:通过 JSON Schema 在库层约束文档结构,插入/更新自动校验,保障数据质量
- 最大文档 16MB:超出用 GridFS 分块;嵌套深度上限 100 层
这构成了"动态 schema"的基础:同一个集合里,不同文档可以有不同字段、不同类型,无需像关系型数据库那样预先 DDL。对从 MongoDB 迁移的应用来说,建表语句、实体映射层基本可以原样保留。
db.people.drop**()**
// 1. 插入嵌套文档 + 数组
db.people.insertOne**({**
name**:** "张三",
age**:** 28**,**
address**:** { city**:** "武汉", district**:** "洪山", zip**:** "430070" },
hobbies**:** ** "篮球"**,** "编程"**,
examScores**:** ** **{** subject**:** "数学"**,** score**:** 92 **},** **{** subject**:** "英语"**,** score**:** 85 **}** **
});
// 2. 插入不同结构文档(演示动态 Schema)
db.people.insertOne**({**
name**:** "李四",
age**:** 32**,**
phone**:** "13800138000",
tags**:** ** "VIP"**,** "2026"**,
address**:** { city**:** "北京" }
});
db.validatedUsers.drop**()**
// 3. 创建带 Schema 验证的集合(若已存在会报错,可先 drop 或改用其他集合名)
db.createCollection**(** "validatedUsers", {
validator**:** {
$jsonSchema**:** {
bsonType**:** "object",
required**:** ** "userName"**,** "age"**,
properties**:** {
userName**:** { bsonType**:** "string" },
age**:** { bsonType**:** "int", minimum**:** 0**,** maximum**:** 120 },
email**:** { bsonType**:** "string", pattern**:** "^.+@.+\\..+$" }
}
}
}
});
// 4. 合法插入(成功)
db.validatedUsers.insertOne**({**
userName**:** "王五",
age**:** NumberInt**(** 25**),**
email**:** "wangwu@example.com"
});
// 5. 非法插入(失败,抛出验证错误)
db.validatedUsers.insertOne**({**
userName**:** "赵六",
age**:** "二十五"
});
// 6. 查看文档大小(以张三为例)
db.people.findOne**({** name**:** "张三" });

五、集合 API 操作(CRUD + 集合管理 + 统计)兼容
增删改查是所有数据库的基本盘。DMDDB 对齐 MongoDB 全套标准读写 API,下面每一项都给了可直接执行的命令,业务代码基本不用改。
5 .1 写入
- insertOne / insertMany:单条与批量插入
- Ordered / Unordered 批量插入:有序遇错即停;无序遇错继续
- updateOne / updateMany / replaceOne:按条件更新、整文档替换
- findOneAndUpdate / findOneAndReplace / findOneAndDelete:带返回值的原子写
- upsert:不存在则插入的"更新或插入"语义
- bulkWrite:批量混合写操作(insert/update/replace/delete)
db.testOps.drop**();**
db.testOps.insertOne**({** name**:** "Alice", age**:** 25 });
db.testOps.insertMany**(** **{** name**:** "Bob"**,** age**:** 30 **},** **{** name**:** "Charlie"**,** age**:** 35 **}** **);**
db.testOps.insertMany**(** **{** _id**:** 1**,** name**:** "David" **},** **{** _id**:** 2**,** name**:** "Frank" **}** **,** { ordered**:** true });
db.testOps.insertMany**(** **{** _id**:** 3**,** name**:** "Grace" **},** **{** _id**:** 4**,** name**:** "Ivan" **}** **,** { ordered**:** false });
db.testOps.find**()** .pretty**();**
db.testOps.updateOne**({** name**:** "Alice" }, { $set**:** { age**:** 26 } });
db.testOps.updateMany**({** age**:** { lt**:** 35 **}** **},** **{** inc**:** { age**:** 1 } });
db.testOps.replaceOne**({** name**:** "Bob" }, { name**:** "Robert", age**:** 31**,** city**:** "New York" });
db.testOps.findOneAndUpdate**({** name**:** "Charlie" }, { $set**:** { age**:** 40 } }, { returnDocument**:** 'before' });
db.testOps.findOneAndReplace**({** name**:** "Robert" }, { name**:** "Bob", age**:** 32**,** city**:** "Los Angeles" }, { returnDocument**:** 'after' });
db.testOps.findOneAndDelete**({** name**:** "Grace" });
db.testOps.updateOne**({** name**:** "Zoe" }, { $set**:** { age**:** 28**,** city**:** "London" } }, { upsert**:** true });
db.testOps.updateOne**({** name**:** "Zoe" }, { $set**:** { age**:** 29 } }, { upsert**:** true });
db.testOps.bulkWrite**(** **{** insertOne**:** **{** document**:** **{** name**:** "Tom"**,** age**:** 22 **}** **}** **},** **{** updateOne**:** **{** filter**:** **{** name**:** "Alice" **},** update**:** **{** $set**:** **{** city**:** "Paris" **}** **}** **}** **},** **{** replaceOne**:** **{** filter**:** **{** name**:** "Ivan" **},** replacement**:** **{** name**:** "Ivan"**,** age**:** 99 **}** **}** **},** **{** deleteOne**:** **{** filter**:** **{** name**:** "Heidi" **}** **}** **}** **);**
db.testOps.find**()** .pretty**();**

5 .2 读取
- find / findOne:基础查询,支持投影(返回字段筛选)
- distinct:去重查询(类似 SQL DISTINCT)
- countDocuments / estimatedDocumentCount:精确计数 / 元数据估算计数
- 嵌套文档查询:点号路径访问(如 "addr.city")
- 嵌套数组查询:数组元素、数组内文档字段匹配
- 游标:limit / skip / sort,大结果集分批拉取
db.testQuery.drop**();**
db.testQuery.insertMany**([**
{ name**:** "Alice", age**:** 25**,** addr**:** { city**:** "Beijing", street**:** "Chang'an" }, tags**:** ** "dev"**,** "lead"**, scores**:** ** **{** subject**:** "math"**,** score**:** 90 **},** **{** subject**:** "eng"**,** score**:** 85 **}** ** },
{ name**:** "Bob", age**:** 30**,** addr**:** { city**:** "Shanghai", street**:** "Nanjing" }, tags**:** ** "ops"**, scores**:** ** **{** subject**:** "math"**,** score**:** 78 **},** **{** subject**:** "eng"**,** score**:** 88 **}** ** },
{ name**:** "Charlie", age**:** 35**,** addr**:** { city**:** "Beijing", street**:** "Wangfujing" }, tags**:** ** "dev"**,** "senior"**, scores**:** ** **{** subject**:** "math"**,** score**:** 95 **},** **{** subject**:** "eng"**,** score**:** 92 **}** ** },
{ name**:** "David", age**:** 28**,** addr**:** { city**:** "Guangzhou", street**:** "Tianhe" }, tags**:** ** "qa"**, scores**:** ** **{** subject**:** "math"**,** score**:** 82 **}** ** },
{ name**:** "Eve", age**:** 22**,** addr**:** { city**:** "Shanghai", street**:** "Huaihai" }, tags**:** ** "dev"**,** "intern"**, scores**:** ** **{** subject**:** "eng"**,** score**:** 79 **}** ** }
]);
db.testQuery.find**()** .pretty**();**
db.testQuery.findOne**({** name**:** "Bob" });
db.testQuery.distinct**(** "addr.city");
db.testQuery.countDocuments**({** age**:** { $gt**:** 25 } });
db.testQuery.estimatedDocumentCount**();**
db.testQuery.find**({** "addr.city": "Beijing" }) .pretty**();**
db.testQuery.find**({** tags**:** "dev" }) .pretty**();**
db.testQuery.find**({** "scores.subject": "math", "scores.score": { $gte**:** 90 } }) .pretty**();**
db.testQuery.find**()** .limit**(** 2**);**
db.testQuery.find**()** .skip**(** 2**)** .limit**(** 2**);**
db.testQuery.find**()** .sort**({** age**:** -1 });
db .testQuery .find ({ "addr.city": "Shanghai" }) .limit ( 1**)** .skip ( 0**)** .sort ({ name**:** 1 });


5 .3 删除
- deleteOne / deleteMany:按条件删除
- drop / dropDatabase:集合与库级删除
use test**;**
db.testDelete.insertMany**({** name**:** "Alice"**,** age**:** 25 **},** **{** name**:** "Bob"**,** age**:** 30 **},** **{** name**:** "Charlie"**,** age**:** 35 **},** **{** name**:** "David"**,** age**:** 40 **});**
db.testDelete.deleteOne**({** name**:** "Alice" });
db.testDelete.deleteMany**({** age**:** { $gt**:** 30 } });
db.testDelete.drop**();**
db.dropDatabase**();**

六、查询与更新运算符兼容
MongoDB 的查询表达力,很大程度来自丰富的运算符体系。查询运算符 33 项、更新运算符 20 项,全部支持。
|-----------------|------------------------------------------------------------------------------------|--------------|
| 运算符类别 | 代表运算符 | 兼容情况 |
| 比较 | eq ne gt gte lt lte in nin | 支持 |
| 逻辑 | and or not nor | 支持 |
| 元素 | exists type | 支持 |
| 求值 | expr mod regex where | 支持 |
| 文本 | text | 支持(含中英文全文) |
| 数组 | all elemMatch size | 支持 |
| 地理空间 | geoWithin geoIntersects near box polygon | 支持 |
| 位运算 | bitsAllSet bitsAllClear bitsAnySet bitsAnyClear | 支持 |
| 投影 | elemMatch slice | 支持 |
| 更新运算符类别 | 代表运算符 | 兼容情况 |
| 字段更新 | set unset rename inc mul min max currentDate setOnInsert | 支持 |
| 数组更新 | push addToSet pop pull pullAll each slice sort position \[\] \
查询运算符举例:地理空间、位运算、投影中的 和 slice、数组 $elemMatch
use testSpecial**;**
db.special.drop**();**
db.special.createIndex**({** loc**:** "2dsphere" });
db.special.insertMany**([**
{ name**:** "A", loc**:** { type**:** "Point", coordinates**:** ** 116.4**,** 39.9** }, flags**:** 5**,** scores**:** ** 80**,** 90**,** 100**, comments**:** {** text**:** "good"**,** votes**:** 1 **},** **{** text**:** "bad"**,** votes**:** 0 **} },
{ name**:** "B", loc**:** { type**:** "Point", coordinates**:** ** 121.5**,** 31.2** }, flags**:** 3**,** scores**:** ** 70**,** 85**, comments**:** {** text**:** "nice"**,** votes**:** 2 **} },
{ name**:** "C", loc**:** { type**:** "Point", coordinates**:** ** 113.2**,** 23.1** }, flags**:** 12**,** scores**:** ** 95**,** 88**,** 92**,** 78**, comments**:** \[\] }
]);
db.special.find**({** loc**:** { near**:** **{** geometry**:** { type**:** "Point", coordinates**:** ** 116**,** 40** }, $maxDistance**:** 500000 } } }) .pretty**();**
db.special.find**({** loc**:** { geoWithin**:** **{** box**:** ** **\[** 110**,** 20**, ** 120**,** 40** ] } } }) .pretty**();**
db.special.find**({** flags**:** { $bitsAllSet**:** 4 } }) .pretty**();**
db.special.find**({** "scores": { elemMatch**:** **{** gte**:** 90**,** $lt**:** 100 } } }) .pretty**();**
db.special.find**({},** { scores**:** { $slice**:** 2 } }) .pretty**();**
db.special.find**({** "comments": { elemMatch**:** **{** text**:** "good" **}** **}** **},** **{** "comments.": 1 }) .pretty**();**


更新运算符举例:
min/max:用于更新字段为较小/较大值。
$currentDate:自动设置为当前日期。
$setOnInsert:只在upsert插入时设置字段。
push配合each、slice、slice、sort、$position:对数组进行复杂更新。
pull和pullAll:删除数组元素。
数组占位符\[\]和\[\]和\
use testUpdates**;**
db.updates.drop**();**
db.updates.insertMany**([**
{ _id**:** 1**,** score**:** 80**,** date**:** null**,** arr**:** ** 1**,** 2**,** 3**, tags**:** ** "a"**,** "b"**, items**:** {** name**:** "x"**,** qty**:** 1 **},** **{** name**:** "y"**,** qty**:** 2 **} },
{ _id**:** 2**,** score**:** 60**,** arr**:** ** 4**,** 5**, tags**:** \[\] }
]);
db.updates.updateOne**({** _id**:** 1 }, { $min**:** { score**:** 90 } });
db.updates.updateOne**({** _id**:** 1 }, { $max**:** { score**:** 70 } });
db.updates.updateOne**({** _id**:** 1 }, { $currentDate**:** { date**:** true } });
db.updates.updateOne**({** _id**:** 3 }, { set**:** **{** name**:** "new" **},** setOnInsert**:** { created**:** new Date**()** } }, { upsert**:** true });
db.updates.updateOne**({** _id**:** 1 }, { push**:** **{** arr**:** **{** each**:** ** 5**,** 4**, slice**:** -3**,** sort**:** 1 } } });
db.updates.updateOne**({** _id**:** 1 }, { $pull**:** { tags**:** "a" } });
db.updates.updateOne**({** _id**:** 1 }, { $pullAll**:** { arr**:** ** 2**,** 3** } });
db.updates.updateOne**({** _id**:** 1 }, { inc**:** **{** "items.\[\].qty": 1 } });
db.updates.updateOne**({** _id**:** 1 }, { inc**:** **{** "items.elem.qty": 10 } }, { arrayFilters**:** {** "elem.name"**:** "x" **} });

七、聚合框架兼容:管道式查询
聚合框架是文档数据库区别于纯 KV 存储和传统关系型数据库的地方:KV 没有聚合能力,关系库需要多次 JOIN 加应用层拼装,而聚合管道一条就能完成过滤、变形、分组、关联、统计。DMDDB 支持 43 个管道阶段、100+ 个聚合表达式操作符。
7.1 聚合管道阶段
|---------------------|-------------------------------------------------------|--------------|
| 阶段 | 作用 | 兼容情况 |
| addFields | 向文档中添加新字段(或修改现有字段),不改变原有结构。 | 支持 |
| count | 统计管道中文档的总数,并作为新文档返回。 | 支持 |
| group | 根据指定字段对文档进行分组,并执行聚合运算(如求和、平均值等)。 | 支持 |
| limit | 限制管道中返回的文档数量。 | 支持 |
| match | 筛选符合条件的文档,类似 find() 的查询条件。 | 支持 |
| project | 重塑文档结构,可包含/排除字段,或计算新字段。 | 支持 |
| set | 与 addFields 功能相同(MongoDB 4.2+ 引入,等同于 addFields)。 | 支持 |
| skip | 跳过指定数量的文档,常用于分页。 | 支持 |
| sort | 根据指定字段对文档进行排序(升序/降序)。 | 支持 |
| unionWith | 合并两个集合的文档结果(并集),需在 unionWith 后指定集合名。 | 支持 |
| unset | 删除文档中的指定字段。 | 支持 |
| unwind | 将数组字段拆分为多条文档,每个数组元素独立为一条。 | 支持 |
| replaceRoot | 用指定的嵌入式文档替换整个输入文档。 | 支持 |
| replaceWith | 与 replaceRoot 功能相同(replaceWith 是 replaceRoot 的别名)。 | 支持 |
| sortByCount | 根据指定表达式的值对文档分组,并计算每个分组的文档数量,结果按计数降序排列。 | 支持 |
| let | 定义变量并在表达式中使用,返回表达式计算结果。 | 支持 |
| literal | 返回原值而不进行解析,用于在聚合管道中避免将值误解析为表达式。 | 支持 |
| split | 根据指定分隔符将字符串拆分为子字符串数组。 | 支持 |
| bucket/bucketAuto | 将文档按照指定范围分桶(分组),每个桶输出一个文档(RAM 限制 100 MB)。 | 支持 |
| dayOfWeek | 返回日期的星期几(1=星期日,7=星期六)。 | 支持 |
| dayOfMonth | 返回日期中的"日"(1~31)。 | 支持 |
| dayOfYear | 返回日期中的"年积日"(1\~366)。 | 支持 |
| isoDayOfWeek | 返回 ISO 标准下的星期几(1=星期一,7=星期日)。 | 支持 |
| isoWeek | 返回 ISO 标准下的周数(1\~53)。 | 支持 |
| isoWeekYear | 返回 ISO 标准下的年份(周数所属年份)。 | 支持 |
| millisecond | 返回日期中的毫秒数(0\~999)。 | 支持 |
| second | 返回日期中的秒数(0~60,考虑闰秒)。 | 支持 |
| minute | 返回日期中的分钟数(0\~59)。 | 支持 |
| hour | 返回日期中的小时数(0~23)。 | 支持 |
| week | 返回日期所在年份的周数(0\~53,周日作为一周起始)。 | 支持 |
| month | 返回日期中的月份(1~12)。 | 支持 |
| year | 返回日期中的年份。 | 支持 |
| dateToParts | 将日期对象拆分为年、月、日、时、分、秒、毫秒等各个字段。 | 支持 |
| dateToString | 将日期格式化为指定格式的字符串。 | 支持 |
| changeStream | 监听集合或数据库的变更事件(插入、更新、删除等),用于实时数据流处理。 | 支持 |
| currentOp | 返回当前数据库操作(活动操作)的信息。 | 支持 |
| graphLookup | 对集合执行递归查找(图遍历),用于层次或关系数据查询。 | 支持 |
| listLocalSessions | 列出当前 MongoDB 实例上的本地会话信息(管理员级操作)。 | 支持 |
| lookup | 执行多集合左外连接查询,类似 SQL 中的 JOIN。 | 支持 |
| merge | 将聚合管道的结果写入目标集合(可合并已有文档,支持更新/插入)。 | 支持 |
| out | 将聚合管道的结果写入目标集合,若集合存在则完全覆盖原有数据。 | 支持 |
| sample | 从输入文档中随机选择指定数量的文档。 | 支持 |
| facet | 在同一组输入文档上并行执行多个聚合管道,输出多个子结果集。 | 支持 |
7.2 聚合表达式操作符(100+ 项支持,含本次实测补正)
|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| 操作符类别 | 代表操作符 | 兼容情况 |
| 数学运算符 | abs,add,ceil,floor,log,log10,divide,exp,mod,round,sqrt,subtract,trunc | 支持 |
| 数组运算符 | arrayElemAt,arrayToObject,concatArrays,filter,first,in,indexOfArray,isArray,last,map,objectToArray,range,reduce,reverseArray,size,firstN(数组),lastN(数组),maxN(数组),minN(数组),zip | 支持 |
| 布尔运算符 | and,not,or | 支持 |
| 比较运算符 | eq,gt,gte,lt,lte,ne,cmp | 支持 |
| 集合运算符 | allElementsTrue,anyElementTrue,setDifference,setEquals,setIntersection,setIsSubset,setUnion | 支持 |
| 三角函数运算符 | sin,cos,tan,asin,acos,atan,atan2,asinh,acosh,atanh,sinh,cosh,tanh,degreesToRadians,radiansToDegrees | 支持 |
| 聚集运算符 | addToSet,avg,max,min,push,sum,stdDevPop,stdDevSamp | 支持 |
| 日期运算符 | dateTrunc,dateAdd,dateDiff,dateSubtract,dateFromParts,dateFromString | 支持 |
| 聚合累加器运算符 | top,topN,bottom,bottomN,firstN,lastN,maxN,minN,count | 支持 |
| 时间戳运算符 | tsIncrement,tsSecond | 支持 |
| 数据大小运算符 | binarySize,bsonSize | 支持 |
| 字符串表达式运算符 | concat,indexOfBytes,regexFindAll,regexMatch,replaceOne,replaceAll,ltrim,rtrim,trim,strcasecmp,strLenBytes,strLenCP,substr,substrBytes,substrCP,toLower,toUpper | 支持 |
| 条件表达式运算符 | cond,switch | 支持 |
| 类型表达式运算符 | convert,isNumber,toBool,toDate,toDecimal,toDouble,toInt,toLong,toObjectId,toString | 支持 |
| 自定义聚合表达式运算符 | function | 支持 |
| 对象表达式运算符 | mergeObjects,setField,unsetField | 支持 |
| 其他运算符 | rand,sampleRate,getField | 支持 |
7.3 深度兼容:复杂聚合测试
复杂聚合管道:完成"过滤 → 关联 → 计算 → 分组 → 多面统计"
// ============ 准备测试数据(订单、客户、产品、分类) ============
db.orders.drop**();**
db.customers.drop**();**
db.products.drop**();**
db.customers.insertMany**([**
{ _id**:** "C001", name**:** "张三", city**:** "北京", regDate**:** ISODate**(** "2024-01-01") },
{ _id**:** "C002", name**:** "李四", city**:** "上海", regDate**:** ISODate**(** "2024-03-15") },
{ _id**:** "C003", name**:** "王五", city**:** "广州", regDate**:** ISODate**(** "2024-06-20") }
]);
db.products.insertMany**([**
{ _id**:** 101**,** name**:** "笔记本电脑", category**:** "电子", price**:** 5000**,** stock**:** 10 },
{ _id**:** 102**,** name**:** "鼠标", category**:** "电子", price**:** 100**,** stock**:** 50 },
{ _id**:** 103**,** name**:** "键盘", category**:** "电子", price**:** 300**,** stock**:** 30 },
{ _id**:** 104**,** name**:** "显示器", category**:** "外设", price**:** 1500**,** stock**:** 8 },
{ _id**:** 105**,** name**:** "椅子", category**:** "家具", price**:** 800**,** stock**:** 5 }
]);
db.orders.insertMany**([**
{ _id**:** 1**,** cust_id**:** "C001", product_id**:** 101**,** qty**:** 1**,** price**:** 5000**,** status**:** "completed", date**:** ISODate**(** "2025-01-15") },
{ _id**:** 2**,** cust_id**:** "C002", product_id**:** 102**,** qty**:** 3**,** price**:** 100**,** status**:** "completed", date**:** ISODate**(** "2025-02-20") },
{ _id**:** 3**,** cust_id**:** "C001", product_id**:** 103**,** qty**:** 2**,** price**:** 300**,** status**:** "completed", date**:** ISODate**(** "2025-03-10") },
{ _id**:** 4**,** cust_id**:** "C003", product_id**:** 101**,** qty**:** 1**,** price**:** 5000**,** status**:** "completed", date**:** ISODate**(** "2025-04-05") },
{ _id**:** 5**,** cust_id**:** "C002", product_id**:** 104**,** qty**:** 1**,** price**:** 1500**,** status**:** "pending", date**:** ISODate**(** "2025-05-12") }, // 暂不统计
{ _id**:** 6**,** cust_id**:** "C003", product_id**:** 105**,** qty**:** 2**,** price**:** 800**,** status**:** "completed", date**:** ISODate**(** "2025-06-01") },
{ _id**:** 7**,** cust_id**:** "C001", product_id**:** 104**,** qty**:** 1**,** price**:** 1500**,** status**:** "completed", date**:** ISODate**(** "2025-07-20") },
{ _id**:** 8**,** cust_id**:** "C002", product_id**:** 103**,** qty**:** 1**,** price**:** 300**,** status**:** "completed", date**:** ISODate**(** "2025-08-10") },
{ _id**:** 9**,** cust_id**:** "C003", product_id**:** 102**,** qty**:** 5**,** price**:** 100**,** status**:** "completed", date**:** ISODate**(** "2025-09-05") },
{ _id**:** 10**,** cust_id**:** "C001", product_id**:** 105**,** qty**:** 1**,** price**:** 800**,** status**:** "completed", date**:** ISODate**(** "2025-10-01") }
]);
// ============ 复杂聚合管道:完成"过滤 → 关联 → 计算 → 分组 → 多面统计" ============
db.orders.aggregate**([**
// 阶段1:过滤 -- 仅保留已完成订单
{ $match**:** { status**:** "completed" } },
// 阶段2:关联客户信息
{ $lookup**:** { from**:** "customers", localField**:** "cust_id", foreignField**:** "_id", as**:** "customer" } },
{ unwind**:** "customer" }, // 展开为单个对象
// 阶段3:关联产品信息
{ $lookup**:** { from**:** "products", localField**:** "product_id", foreignField**:** "_id", as**:** "product" } },
{ unwind**:** "product" },
// 阶段4:计算订单金额,并提取需要的字段
{ $addFields**:** {
orderAmount**:** { multiply**:** **\[** "qty", "$price"] },
orderYear**:** { year**:** "date" },
customerRegYear**:** { year**:** "customer.regDate" },
productCategory**:** "$product.category"
} },
// 阶段5:按客户分组,计算聚合指标
{ $group**:** {
_id**:** "$cust_id",
name**:** { first**:** "customer.name" },
city**:** { first**:** "customer.city" },
regYear**:** { first**:** "customerRegYear" },
totalAmount**:** { sum**:** "orderAmount" },
avgAmount**:** { avg**:** "orderAmount" },
orderCount**:** { $sum**:** 1 },
maxOrder**:** { max**:** "orderAmount" },
categories**:** { addToSet**:** "productCategory" } // 购买过的品类(去重)
} },
// 阶段6:添加客单价字段
{ $addFields**:** {
avgPerOrder**:** { divide**:** **\[** "totalAmount", "$orderCount"] },
categoryCount**:** { size**:** "categories" }
} },
// 阶段7:投影,只保留最终需要的字段
{ $project**:** {
_id**:** 0**,**
customerId**:** "$_id",
name**:** 1**,**
city**:** 1**,**
regYear**:** 1**,**
totalAmount**:** 1**,**
avgAmount**:** 1**,**
orderCount**:** 1**,**
maxOrder**:** 1**,**
avgPerOrder**:** 1**,**
categories**:** 1**,**
categoryCount**:** 1
} },
// 阶段8:使用 $facet 同时生成两个分析维度
{ $facet**:** {
// 维度A:客户明细(按总金额降序取前3)
customerTop**:** [
{ $sort**:** { totalAmount**:** -1 } },
{ $limit**:** 3 }
],
// 维度B:整体统计(汇总全部客户)
overallStats**:** [
{ $group**:** {
_id**:** null**,**
totalOrders**:** { sum**:** "orderCount" },
totalRevenue**:** { sum**:** "totalAmount" },
avgRevenuePerCustomer**:** { avg**:** "totalAmount" },
maxSingleOrder**:** { max**:** "maxOrder" }
} },
{ $project**:** { _id**:** 0 } }
]
} }
]);

八、索引能力兼容
索引决定查询性能与表达力。索引类型 12 项全部支持,通过 createIndex / getIndexes / dropIndex / reIndex 管理。
|--------------|--------------------|--------------|
| 索引类型 | 说明 | 兼容情况 |
| 单字段索引 | 对单个字段建索引 | 支持 |
| 复合索引 | 多字段组合,支持前缀匹配 | 支持 |
| 多键索引 | 数组字段自动展开建索引 | 支持 |
| 哈希索引 | 对字段做哈希计算,适合等值查询 | 支持 |
| 唯一索引 | 保证字段值唯一(_id 默认唯一) | 支持 |
| 部分索引 | 仅对满足过滤条件的文档建索引 | 支持 |
| TTL 索引 | 按时间自动过期文档(会话/日志清理) | 支持 |
| 文本索引 | 全文检索,含中英文分词 | 支持 |
| 地理索引 | 2d / 2dsphere,空间查询 | 支持 |
| 稀疏索引 | 跳过缺失字段 | 支持 |
| 通配符索引 | 对动态/嵌套字段建索引 | 支持 |
| 隐藏索引 | 灰度评估时隐藏、不删除 | 支持 |
需要单独说明的是中文全文检索:DMDDB 的文本索引支持中英文混合分词。内容检索、日志检索、工单检索这类需求在国产替代场景很常见,只做英文分词的方案难以覆盖。
中文全文检索命中 :
use test_text**;**
db.articles.drop**();**
// 1. 插入中英文混合测试数据
db.articles.insertMany**([**
{ _id**:** 1**,** title**:** "DMDDB 中文教程", content**:** "达梦文档数据库支持中文全文搜索,性能卓越。" },
{ _id**:** 2**,** title**:** "Database 性能优化", content**:** "全文检索在海量数据下表现优异。" },
{ _id**:** 3**,** title**:** "达梦功能介绍", content**:** "支持中文分词,在达梦数据库中查询中文非常方便。" },
{ _id**:** 4**,** title**:** "对比 Elasticsearch", content**:** "文档数据库内置全文索引,无需额外组件。" }
]);
// 2. 创建中文全文索引
db.articles.createIndex**({** title**:** "text", content**:** "text" }, { default_language**:** "chinese" });
// 3. 执行中文全文检索(查询关键词:"达梦 中文"),并附带相关性评分
db.articles.find**(**
{ text**:** **{** search**:** "达梦 中文" } },
{ score**:** { $meta**:** "textScore" } }
) .sort**({** score**:** { $meta**:** "textScore" } }) .pretty**();**

TTL 索引过期自动删除:
use test_ttl**;**
db.logs.drop**();**
// 1. 插入带时间戳的文档
db.logs.insertMany**([**
{ _id**:** 1**,** msg**:** "启动日志", createdAt**:** new Date**()** },
{ _id**:** 2**,** msg**:** "业务日志A", createdAt**:** new Date**()** },
{ _id**:** 3**,** msg**:** "业务日志B", createdAt**:** new Date**()** }
]);
// 2. 查看当前数据数量(应为 3)
print**(** "插入后文档数: " + db.logs.count**());**
// 3. 创建 TTL 索引:设定 60 秒后自动删除
db.logs.createIndex**({** createdAt**:** 1 }, { expireAfterSeconds**:** 60 });
print**(** "TTL 索引已创建,等待 60 秒后自动清理...");

九、事务与一致性兼容
多文档事务是 MongoDB 4.0 引入的企业级能力。DMDDB 支持 snapshot 快照读。
- 多文档事务:startSession → startTransaction → commitTransaction / abortTransaction → endSession
- 回滚:业务异常时 abortTransaction 回滚,未提交数据对外不可见
- 事务内查询:find、聚合、游标遍历等读操作在事务快照内一致执行
- 一致性级别: snapshot 快照读、因果一致性(Causal Consistency)
// 准备数据
use test_txn**;**
db.accounts.drop**()**
db.accounts.insertMany**({** _id**:** "A"**,** balance**:** 100 **},** **{** _id**:** "B"**,** balance**:** 50 **});**
// 多文档事务示例(转账 30 元)
var session = db.getMongo**()** .startSession**();** // 创建会话
var coll = session.getDatabase**(** "test_txn") .getCollection**(** "accounts");
session.startTransaction**();** // 开启事务(默认 snapshot 快照读)
try {
var from = coll.findOne**({** _id**:** "A" }); // 快照读:事务开始时的余额
if ( from.balance < 30**)** throw new Error**(** "余额不足");
coll.updateOne**({** _id**:** "A" }, { $inc**:** { balance**:** -30 } });
coll.updateOne**({** _id**:** "B" }, { $inc**:** { balance**:** 30 } });
session.commitTransaction**();** // 提交:原子生效
print**(** "✅ 提交成功");
} catch ( e**)** {
session.abortTransaction**();** // 回滚:所有变更撤销
print**(** "❌ 回滚");
} finally {
session.endSession**();** // 结束会话
}
// 验证结果(事务外可见已提交的数据)
db .accounts .find ();

十、GridF S兼容
GridFS:大文件分块存储(支持20G+大文件),兼容 MongoDB GridFS 协议,驱动可直接读写.

十 一、Change Stream 兼容
Change Stream:支持集合级 / 数据库级 / 集群级 watch() 监听
fullDocument:可返回变更后的完整文档
文档前像 / 后像(Pre-image / Post-image):changeStreamPreAndPostImages 增强特性,可同时返回变更前后完整镜像,便于下游做 diff 级处理

十二、客户端工具生态兼容:图形化客户端直连
兼容性不能只停留在命令行,DBA 和开发日常用的是图形化客户端。多款主流 MongoDB 客户端都能直连 DMDDB。
|--------------------------------------------------|--------------------------------|------------------|
| 客户端/中间件 | 类型 | 兼容情况 |
| Studio 3T | 图形化 MongoDB 客户端(功能最全) | 支持 |
| Navicat for MongoDB | 图形化客户端(跨库管理) | 支持 |
| NosqlBooster for MongoDB | 图形化客户端(含 Shell 增强) | 支持 |
| Compass | MongoDB Compass 是官方图形化 GUI 客户端 | 支持 |
| mongosh / 传统 mongo shell | 官方 Shell | 支持(mongosh 实测直连) |



十三、多语言驱动兼容
应用不直接连数据库,中间隔着一层驱动,驱动兼容才是"不改代码"的关键。官方驱动、连接池、Stable API 均支持。
|-------------------------|-------------------------------|--------------|
| 语言/框架 | 驱动基线 | 兼容情况 |
| Java | mongodb-driver-core 4.6.1 及以上 | 支持 |
| GO | mongo-driver 1.11.1 及以上 | 支持 |
| Node.js | mongodb 官方驱动(6.6.2+ 环境) | 支持 |
| Python | pymongo | 支持 |
| Spring Data for MongoDB | Spring 生态框架 | 支持 |
| C/C++ | | 支持 |
| 其他官方驱动 | 遵循 MongoDB 驱动规范(含连接池) | 协议级兼容 |



十四、数据柔性迁移与数据校验
从 MongoDB 迁移至 DMDDB 提供全链路支持,按迁移评估、全量迁移、增量同步、数据校验、灰度切换五个阶段推进,迁移期间源库可持续写入,业务低感知。
- 迁移评估:梳理源库的算子使用、索引定义与数据规模,输出兼容性评估结论与迁移方案
14.1 数据柔性迁移
- 全量迁移:兼容 mongodump / mongorestore、mongoexport / mongoimport / ddb_importer工具链,支持并行导入,存量数据可直接迁入
- 增量同步:基于 Change Stream 持续捕获源库增量变更,实现"全量 + 增量"连续迁移,增量追平后即可切换,目前已有成熟的同步工具DMDIS提供使用
- 灰度切换:迁移期间新旧库并行运行,业务可按集合或流量比例逐步切流;源库保留至业务稳定运行,异常时可快速回退
14.2 数据校验
- 数量校验:按集合比对文档数量、索引数量,确认迁移对象完整
- 内容校验:支持抽样比对(比例可配置)与全量比对,覆盖字段值与 BSON 类型一致性,确保数据零差异
- 元数据校验:比对库、集合结构与索引定义,确认迁移后对象与源库一致
- 差异定位:输出校验结果,差异项可定位到具体文档,便于修复与复核
针对文档数据库之间数据同步之后的数据一致性校验的问题,目前已经在成熟的数据校验工具DMDVS的基础上进行适配,可以保证MongoDB和DMDDB之间数据柔性迁移之后数据一致性
十 五 、 DMDDB 兼容性速查
|-------------------|--------------------------------------------------------------------------------|---------------|
| 能力点 | MongoDB 对应 | DMDDB |
| 协议直连 | wire protocol / 27017 | 支持 |
| BSON 类型 | 16 类 | 支持 |
| 数据模型 | 动态 Schema / JSON Schema 验证 | 支持 |
| 集合 API | 20+项(含 distinct/bulkWrite) | 支持 |
| 查询运算符 | 33 项(含数组/位运算/投影) | 支持 |
| 更新运算符 | 20 项(字段/数组) | 支持 |
| 聚合管道 | 43阶段 | 支持 |
| 聚合操作符 | 100+ 运算符 | 支持 |
| 索引 | 12 类(含中英文全文/哈希) | 支持 |
| 多文档事务 | 多文档 ACID + snapshot | 支持 |
| GridFS | 20G+大文件 | 支持 |
| Change Stream | watch / Pre-Post image | 支持 |
| 客户端 | Studio 3T / Navicat / NosqlBoosterforMongoDB/ Compass | 支持 |
| 驱动 | Java/GO/Node/Python/C/C++ + Stable API | 支持 |
| 框架 | Spring Data MongoDB | 支持 |
| 运维 | dump/restore/explain/profiler/serverStatus/dbStats/collStats/currentOp/ killOp | 支持 |
十六、总结与迁移建议
达梦文档数据库 DMDDB 基于自研原生文档引擎与存储计算分离架构,实现了从底层通信协议、数据模型、核心 API 到工具生态、运维安全的MongoDB 全链路兼容。经过实测验证,对绝大多数存量 MongoDB 应用,仅需修改数据库连接串即可完成平滑迁移,业务代码无需大规模改造;少数依赖MongoDB 特定内核行为的场景,建议结合业务实测确认。
迁移参考建议
- 常规业务场景:以 CRUD、聚合查询、事务为主的标准业务应用,可直接通
过修改连接串迁移,迁移成本极低;
- 复杂特性场景:使用地理空间查询、全文检索、Change Stream 等高级特性
的应用,建议提前进行功能验证,DMDDB 均已兼容对应能力;
- 规模选型:中小规模业务可选择单机部署,大规模、高可用要求的业务可选
择分布式集群部署,按需弹性扩展。
DMDDB 在全面兼容 MongoDB 生态的同时,依托达梦数据在数据库领域的
技术积累,提供稳定的企业级能力与国产化服务支撑,是文档数据库信创替代
的优选方案。