MongoDB 4.X CRUD基本操作

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

MongoDB 4.X CRUD基本操作

mangoDB
目录

创建(Create Operations)
db.collection.insert()
db.collection.insertOne()
db.collection.insertMany()
关于返回确认信息
查询(Read Operations)
db.collection.find()
db.collection.findOne()
条件查询操作符
更新(Update Operations)
db.collection.update()
db.collection.updateOne()
db.collection.updateMany()
删除(Delete Operations)
db.collection.deleteOne()
db.collection.deleteMany()
总结
参考
正文

本文总结了MongoDB 4.X在mongo shell客户端涉及的对文档一些基本的增删改查操作,即CRUD操作。主要结合了自己平时使用MongoDB的操作命令,更详细的命令可以参考官方文档: https://docs.mongodb.com/manual/crud/ 。

回到顶部
创建(Create Operations)
创建(Create Operations)也叫插入操作,当集合不存在时,插入操作同时也会创建集合。MongoDB提供以下几种插入文档方法:

db.collection.insert():在指定集合中插入单个或多个文档。
db.collection.insertOne():在指定集合中插入单个文档(版本3.2新增)。
db.collection.insertMany():在指定集合中插入多个文档(版本3.2新增)。
回到顶部
db.collection.insert()
在平时的使用当中,db.collection.insert()是我用得最多的文档插入方式,具体的语法格式如下:

db.collection.insert(
,
{

 writeConcern: <document>,
 ordered: <boolean>

}
)
参数说明:

document:指定一个或多个文档;
writeConcern:文档写入确认级别(可选),关于读写策略确认级别,以后再进行讨论;
ordered:指定文档是否按顺序插入(可选),默认为true;
当指定为true时,插入多个文档时将文档排序保存在一个数组中进行插入,如果其中有一个文档插入失败,则会导致数组中余下的文档不进行插入操作;
当指定为false时,插入多个文档时将文档不进行排序保存在一个数组中进行插入,如果其中有一个文档插入失败,则不影响数组中余下的文档进行插入操作。
如果插入的文档当中没有指定_id字段,则MongoDB会自动为文档生成具有唯一ObjectId值的字段_id。

使用示例:

// 没有指定_id字段的插入单个文档
db.products.insert( { item: "card", qty: 15 } );

// 指定_id字段的插入单个文档
db.products.insert( { _id: 10, item: "box", qty: 20 } );

// 插入多个文档,不进行排序,多个文档包含在数组[]中
db.products.insert(
[

 { _id: 11, item: "pencil", qty: 50, type: "no.2" },
 { item: "pen", qty: 20 },
 { item: "eraser", qty: 25 }

]
);

// 插入多个文档,并进行排序
db.products.insert(
[

 { _id: 20, item: "lamp", qty: 50, type: "desk" },
 { _id: 21, item: "lamp", qty: 20, type: "floor" },
 { _id: 22, item: "bulk", qty: 100 }

],
{ ordered: false }
);

回到顶部
db.collection.insertOne()
语法格式如下:

db.collection.insertOne(
,
{

  writeConcern: <document>

}
)
参数说明:

参考db.collection.insert()的参数说明。

使用示例:

// 单行插入文档,关于_id字段指定与否也与db.collection.insert()一致
db.products.insertOne( { item: "card", qty: 15 } );
回到顶部
db.collection.insertMany()
语法格式如下:

db.collection.insertMany(
[ , , ... ],
{

  writeConcern: <document>,
  ordered: <boolean>

}
)
参数说明:

参考db.collection.insert()的参数说明。

使用示例:

参考db.collection.insert()的参数说明。

回到顶部
关于返回确认信息
db.collection.insert()在插入文档成功之后返回的信息相对较为简洁:

db.products.insert( { item: "card", qty: 15 } );
WriteResult({ "nInserted" : 1, "writeConcernError" : [ ] })
db.collection.insertOne()和db.collection.insertMany()返回的信息较为详细:

db.products.insertOne( { item: "card", qty: 15 } );
{

"acknowledged": true,
"insertedId": ObjectId("5eccbd214139000074003be8")

}

db.products.insertMany( [

  { _id: 10, item: "large box", qty: 20 },
  { _id: 11, item: "small box", qty: 55 },
  { _id: 12, item: "medium box", qty: 30 }

] );
{

"acknowledged": true,
"insertedIds": [
    10,
    11,
    12
]

}
回到顶部
查询(Read Operations)
查询(Read Operations)读操作,是对集合中已存在的文档进行查询,即对应关系型数据库当中的select操作,比如MySQL,MongoDB提供以下几种主要查询文档方法:

db.collection.find():查询指定集合中满足条件的一个或多个文档和视图;
db.collection.findOne():查询指定集合中满足条件的第一个文档,并以格式化方式展现,通过pretty()方法。
来自官方文档的测试数据:

db.inventory.insertMany([
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
回到顶部
db.collection.find()
db.collection.find()可以说是使用频率最高的方法了,可以用来查询数据库集合当中的文档。

语法格式如下:

db.collection.find(, )
query:查询表达式;
projection:指定查询结果集中需要显示的字段。
Col_name:1|true 代表显示该字段;
Col_name:0 | false 代表不显示该字段。
_id字段是默认显示的,如果不想显示,则显式指定{"_id" : 0}。

查询所有文档:

db.inventory.find()

db.inventory.find({})
回到顶部
db.collection.findOne()
db.collection.findOne()方法显示符合条件查询的第一条文档,接受的参数与db.collection.find()方法一致。

回到顶部
条件查询操作符
通常对文档的查询,是需要带条件的,而很少使用到不带条件的全文档检索,以下总结了几种常使用的查询操作符:

比较操作符
比较操作符涉及的操作如下表所示:

名称 说明
$eq 与指定值相等
$gt 大于指定的值
$gte 大于或等于指定的值
$in 指定的值在数组中
$lt 小于指定的值
$lte 小于或等于指定的值
$ne 所有不等于指定的值
$nin 指定的值不在数组中
使用示例:

// $eq:等值查询 SQL: SELECT * FROM inventory WHERE status = "D";
db.inventory.find( { status: "D" } )

// $ne 同$eq

// $gt:范围查询(以大于为例) SQL: SELECT * FROM inventory WHERE qty > 30;
db.inventory.find( { qty: { $gt: 30 } } )

// $gte、$lt、$lte 同$gt

// $in:或查询,可使用or代替 SQL: SELECT * FROM inventory WHERE status in ("A", "D")
db.inventory.find( { status: { $in: [ "A", "D" ] } } )

// $nin 同$in
逻辑操作符
逻辑操作符涉及的操作如下表所示:

名称 说明
$and 指定查询同时满足多个条件查询子句
$not 指定查询不满足条件查询子句
$nor 指定查询无法满足多个条件查询子句
$or 指定查询满足其中某个条件查询子句
使用示例:

// $and: 逻辑与查询 SQL: SELECT * FROM inventory WHERE status = "A" AND qty < 30;
db.inventory.find( { $and: [ { status: { $eq: "A" }, qty: { $lt: 30 } } ] } )

// $not: 不符合查询 SQL: SELECT * FROM inventory WHERE status <> "A";
db.inventory.find( { status: { $not: { $eq: "A" } } } )

/*
$nor: 无法同时满足多个条件查询,字段不存在时也符合 SQL: SELECT * FROM inventory WHERE status <> "A" AND qty > 30;
符合以下条件之一都会出现在结果集中:
1.文档包含status和qty字段并且符合条件;
2.文档包含status字段并且符合条件,不包含qty字段;
3.文档不包含status字段,包含qty字段并且符合条件;
4.文档不包含status字段和qty字段。
*/
db.inventory.find( { $nor: [ { status: { $eq: "A" } }, { qty: { $lt: 30 } } ] } )

// $or: 逻辑或查询 SQL: SELECT * FROM inventory WHERE status = "A" OR qty < 30;
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
元素操作符
元素操作符主要涉及的操作如下表所示:

名称 说明
$exists 指定查询文档是否有对应的字段
$type 指定查询文档的某个字段是否是对应类型
使用示例:

// $exists: 是否存在指定字段查询
db.inventory.find( { price: { $exists: true } } )

// $type: 字段是否是指定类型查询
db.inventory.find( { "qty": { $type: "double" } } )
评估操作符
评估操作符主要涉及的操作如下表所示,更多操作符可以参考官方文档:https://docs.mongodb.com/manual/reference/operator/query-evaluation/

名称 说明
$expr 为同一个文档中的字段指定表达式并且符合条件的查询,比如比较同一文档当中两个字段的值
$mod 为字段值取模并且符合条件的查询
为了更好的使用这两个主要的操作符,额外创建个文档:

db.monthlyBudget.insertMany([

{ "_id" : 1, "category" : "food", "budget": 400, "spent": 450 },
{ "_id" : 2, "category" : "drinks", "budget": 100, "spent": 150 },
{ "_id" : 3, "category" : "clothes", "budget": 100, "spent": 50 },
{ "_id" : 4, "category" : "misc", "budget": 500, "spent": 300 },
{ "_id" : 5, "category" : "travel", "budget": 200, "spent": 650 }

]);
使用示例:

// $expr: 允许使用聚合表达式,这里以$gt为例,更多表达式参考 https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#aggregation-expressions
db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )

// $mod: 对字段所在值进行取模运算,显示符合条件的查询,如qty字段值对4取模,并且余数为0
db.inventory.find( { qty: { $mod: [ 4, 0 ] } } )
回到顶部
更新(Update Operations)
更新(Update Operations)是对已存在的文档进行修改操作,MongoDB提供以下几种主要更新文档方法:

db.collection.update():更新或替换集合中符合条件的一个或多个文档;
db.collection.updateOne():只更新集合中符合条件的第一个文档,即使有多个文档(版本3.2新增);
db.collection.updateMany():更新集合中所有符合条件的文档(版本3.2新增)。
回到顶部
db.collection.update()
根据update指定的表达式可以修改文档中符合条件的字段或代替整个文档。具体的语法格式如下:

db.collection.update(
, //查询表达式
, //更新表达式
{

 upsert: <boolean>,
 multi: <boolean>,
 writeConcern: <document>,
 collation: <document>,
 arrayFilters: [ <filterdocument1>, ... ],
 hint:  <document|string>                   // 版本4.2新增

}
)
参数说明:

query:更新文档的查询表达式;如果指定了参数upsert: true并且集合中没有符合查询条件的文档,查询条件中有关于字段_id指定了.分隔符的,并不会插入新的文档;
update:主要包含三种格式
1.更新文档:只包含更新操作符表达式;
2.替换文档:只包含: 对;
3.聚合管道:版本4.2新增,详细参考官方文档。
upsert:当query查询条件没符合更新的文档,就新创建文档(可选),默认值为false;
multi:是否更新多个符合条件的文档(可选),默认值为false,只更新符合条件的第一个文档;
writeConcern:参考db.collection.insert()相同参数说明;
collation:指定校对规则(可选,版本3.4新增);
arrayFilters:文档数组更新过滤操作符(可选,版本3.6新增);
详细参考:https://docs.mongodb.com/manual/reference/method/db.collection.update/#specify-arrayfilters-for-array-update-operations

hint:采用文档或字符串的形式指定适用于查询表达式的索引,如果索引不存在则报错(可选,版本4.2新增)。
使用示例:

使用示例将通过使用两种场景进行,一是没有使用参数选项upsert,二是使用参数选项upsert。

不使用选项upsert
// 测试数据
db.books.remove({});

db.books.insertMany([
{

"_id" : 1,
"item" : "TBD",
"stock" : 0,
"info" : { "publisher" : "1111", "pages" : 430 },
"tags" : [ "technology", "computer" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "lmn", "rating" : 5 } ],
"reorder" : false

},
{

"_id" : 2,
"item" : "XYZ123",
"stock" : 15,
"info" : { "publisher" : "5555", "pages" : 150 },
"tags" : [ ],
"ratings" : [ { "by" : "xyz", "rating" : 5 } ],
"reorder" : false

}
]);

/* 使用选项参数 upsert: true
1、如果查询表达式找到匹配的文档,则执行更新操作;
2、如果查询表达式没有找到匹配的文档,则执行插入操作;
*/
db.books.update(
{ item: "ZZZ135" }, // 查询表达式
{ // 更新或替换文档

 item: "ZZZ135",
 stock: 5,
 tags: [ "database" ]

},
{ upsert: true }
);

// 1.使用更新操作表达式
/* $set操作符
1、查询表达式指定需要更新的文档 _id;
2、$inc操作符: stock的字段值+5;
3、$set操作符: 替换item字段值,替换嵌入文档info的publisher字段值,替换tags字段值,替换数组ratings的第二个元素值
*/
db.books.update(
{ _id: 1 },
{

 $inc: { stock: 5 },
 $set: {
   item: "ABC123",
   "info.publisher": "2222",
   tags: [ "software" ],
   "ratings.1": { by: "xyz", rating: 3 }
 }

}
);
更新之后的文档:
{

"_id" : 1,
"item" : "ABC123",
"stock" : 5,
"info" : { "publisher" : "2222", "pages" : 430 },
"tags" : [ "software" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "xyz", "rating" : 3 } ],
"reorder" : false
}

// 2.为已存在的数组添加元素
// $push操作符: 为指定文档数组ratings添加一个元素
db.books.update(
{ _id: 2 },
{

 $push: { ratings: { "by" : "jkl", "rating" : 2 } }

}
);
更新之后的文档:
{
"_id" : 2,
"item" : "XYZ123",
"stock" : 15,
"info" : {
"publisher" : "5555",
"pages" : 150
},
"tags" : [ ],
"ratings" : [
{ "by" : "xyz", "rating" : 5 },

{ "by" : "jkl", "rating" : 2 }

],
"reorder" : false
}

// 3.文档移除字段
// $unset操作符: 移除文档的指定字段,为_id:1文档移除tags字段
db.books.update( { _id: 1 }, { $unset: { tags: 1 } } );
更新后的文档:
{
"_id" : 1,
"item" : "TBD",
"stock" : 0,
"info" : {
"publisher" : "1111",
"pages" : 430
},
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "lmn", "rating" : 5 } ],
"reorder" : false
}

// 4.替换整个文档
// 替换_id:2的文档
db.books.update(
{ _id: 2 },
{

 item: "XYZ123",
 stock: 10,
 info: { publisher: "2255", pages: 150 },
 tags: [ "baking", "cooking" ]

}
);
更新后的文档:
{
"_id" : 2,
"item" : "XYZ123",
"stock" : 10,
"info" : { "publisher" : "2255", "pages" : 150 },
"tags" : [ "baking", "cooking" ]
}

// 5.更新多个文档
db.books.update(
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{ multi: true }
);
更新后的全部文档:
[
{

"_id" : 1,
"item" : "ABC123",
"stock" : 5,
"info" : {
 "publisher" : "2222",
 "pages" : 430
},
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "xyz", "rating" : 3 } ],

"reorder" : true

}
{

 "_id" : 2,
 "item" : "XYZ123",
 "stock" : 10,
 "info" : { "publisher" : "2255", "pages" : 150 },
 "tags" : [ "baking", "cooking" ],

 "reorder" : true

}
]
使用upserts选项
/* 使用选项参数 upsert: true
1、如果查询表达式找到匹配的文档,则执行更新操作;
2、如果查询表达式没有找到匹配的文档,则执行插入操作;
*/

// 1.插入未符合更新条件的文档
db.books.update(
{ item: "ZZZ135" },
{

 item: "ZZZ135",
 stock: 5,
 tags: [ "database" ]

},

{ upsert: true }

);
因为集合并未满足条件的文档,则插入的文档为:
{
"_id" : ObjectId("5da78973835b2f1c75347a83"),
"item" : "ZZZ135",
"stock" : 5,
"tags" : [ "database" ]
}

// 2.插入未符合更新条件并且基于更新操作符的文档
// 如果没有符合更新查询条件,并且使用的是更新操作符,则会基于当前的查询条件和更新操作符字段插入新的文档
db.books.update(
{ item: "BLP921" },
{

  $set: { reorder: false },
  $setOnInsert: { stock: 10 }

},
{ upsert: true }
);
新插入的文档为:
{
"_id" : ObjectId("5da79019835b2f1c75348a0a"),
"item" : "BLP921",
"reorder" : false,
"stock" : 10
}

// 3.插入未符合更新条件并且基于聚合管道的文档
// 关于聚合管道请参考官方文档:https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline

// 4.插入未符合更新条件并且同时联合多文档操作符的文档
如果不符合查询条件,则只会插入单个文档
db.books.update(
{ "info.publisher": "Self-Published" },
{

$set: { reorder: false, tags: [ "literature", "hardcover" ], stock: 25 }

},
{ upsert: true, multi: true }
);
新插入的文档:
{
"_id" : ObjectId("5db337934f670d584b6ca8e0"),
"info" : { "publisher" : "Self-Published" },
"reorder" : false,
"stock" : 25,
"tags" : [ "literature", "hardcover" ]
}
回到顶部
db.collection.updateOne()
根据update指定的参数可以修改文档中符合条件的字段或代替整个文档,与db.collection.update()不同的是每次只更新单个文档。

语法格式如下:

db.collection.updateOne(
,
,
{

 upsert: <boolean>,
 writeConcern: <document>,
 collation: <document>,
 arrayFilters: [ <filterdocument1>, ... ],
 hint:  <document|string>        

}
)
参数说明:

参考db.collection.update()的参数说明。

使用示例:

// 参考db.collection.update()
回到顶部
db.collection.updateMany()
根据update指定的参数可以修改文档中符合条件的字段或代替整个文档,与db.collection.updateOne()不同的是更新所有符合条件的文档。

语法格式如下:

db.collection.updateMany(
,
,
{

 upsert: <boolean>,
 writeConcern: <document>,
 collation: <document>,
 arrayFilters: [ <filterdocument1>, ... ],
 hint:  <document|string>        

}
)
参数说明:

参考db.collection.update()的参数说明。

使用示例:

// 参考db.collection.update()
回到顶部
删除(Delete Operations)
删除是指对集合当中已存在的文档进行清除操作,MongoDB提供以下几种主要删除文档方法:

db.collection.deleteOne():只删除集合中符合条件的一个文档;
db.collection.deleteMany():删除集合中所有符合条件的文档;
db.collection.remove():删除集合中符合条件的一个或多个文档。
回到顶部
db.collection.deleteOne()
根据filter选项条件删除集合中的单个文档,具体语法格式如下:

db.collection.deleteOne(
,
{

  writeConcern: <document>,
  collation: <document>

}
)
参数说明:

filter:指定基于查询表达式的过滤条件,关于查询表达式可以查看db.collecion.find()中的;
writeConcern:参考db.collection.insert()相同参数说明;
collation:指定校对规则(可选,版本3.4新增);
使用示例:

// 删除指定条件的单个文档
db.orders.deleteOne( { "_id" : 1 } );
{ "acknowledged" : true, "deletedCount" : 1 }
回到顶部
db.collection.deleteMany()
根据filter选项条件删除集合中的单个文档,具体语法格式如下:

db.collection.deleteMany(
,
{

  writeConcern: <document>,
  collation: <document>

}
)
参数说明:

参考db.collection.deleteOne()的参数说明。

使用示例:

// 删除指定条件的多个文档
db.orders.deleteMany( {"cust_id" : "Cam Elot"} );
{ "acknowledged" : true, "deletedCount" : 2 }
注意: 如果是对固定集合进行删除文档操作则会报错,固定集合的清除操作使用方法db.collection.drop()。

回到顶部
总结
本文简单梳理了在Mongo Shell下基本的CRUD操作,主要适用于DBA的运维管理,如果是研发同学,根据不同的编程语言使用不同客户端驱动进行操作,详细同样可以参考官方文档;
针对CRUD各个方面还有其他一些额外的方法,比如查询修改文档方法db.collection.findAndModify(),这里只是总结每个文档操作中一些最基础的方法,对于额外高级的方法这里不再赘述;
掌握了这些基本的CRUD操作,就可以对MongoDB文档进行操作了,但还是需要控制好权限,毕竟数据安全不是小事,做变更之前做好数据的备份,以防万一。
回到顶部
参考
https://docs.mongodb.com/manual/crud/

https://docs.mongodb.com/manual/reference/operator/query-evaluation/

https://docs.mongodb.com/manual/reference/method/db.collection.update/#specify-arrayfilters-for-array-update-operations

https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline

☆〖本人水平有限,文中如有错误还请留言批评指正!〗☆

作者: H_Johnny
出处: http://www.cnblogs.com/dbabd/

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
JSON NoSQL MongoDB
mongodb基本操作,增删改查,查询,索引,权限机制
mongodb基本操作,增删改查,查询,索引,权限机制
|
1月前
|
NoSQL Java MongoDB
Springboot WebFlux项目结合mongodb进行crud
这篇文章介绍了如何使用Spring Boot WebFlux框架结合MongoDB进行基本的CRUD(创建、读取、更新、删除)操作,包括项目设置、实体类和Repository的创建、控制器的实现以及配置文件的编写。
46 0
Springboot WebFlux项目结合mongodb进行crud
|
2月前
|
NoSQL MongoDB 数据库
python3操作MongoDB的crud以及聚合案例,代码可直接运行(python经典编程案例)
这篇文章提供了使用Python操作MongoDB数据库进行CRUD(创建、读取、更新、删除)操作的详细代码示例,以及如何执行聚合查询的案例。
32 6
|
6月前
|
NoSQL MongoDB 数据库
MongoDB黑窗口操作(CRUD)
MongoDB黑窗口操作(CRUD)
|
6月前
|
NoSQL Java 关系型数据库
让 MongoDB 的 CRUD 有 JPA 的味道
让 MongoDB 的 CRUD 有 JPA 的味道
100 0
|
6月前
|
NoSQL 关系型数据库 MySQL
使用 MongoTemplate 对 MongoDB 进行 CRUD
使用 MongoTemplate 对 MongoDB 进行 CRUD
122 0
|
6月前
|
NoSQL JavaScript 前端开发
MongoDB【CRUD练习-条件查询-文档关系】
MongoDB【CRUD练习-条件查询-文档关系】
|
6月前
|
JSON NoSQL MongoDB
MongoDB【CRUD基本操作】
MongoDB【CRUD基本操作】
|
存储 JSON NoSQL
02 MongoDB - 基本操作
02 MongoDB - 基本操作
25 0
|
SQL NoSQL MongoDB
MongoDB 操作(CRUD) 教程—官方原版
MongoDB 操作(CRUD) 教程—官方原版
206 0