MongoDB
参考网址
https://mongodb.net.cn/manual/tutorial/getting-started/
-中文手册
https://www.runoob.com/mongodb/mongodb-connections.html
-菜鸟教程
https://developer.aliyun.com/article/54367
-writeConcern原理解析
https://www.cnblogs.com/shanyou/p/3494854.html
- MongoDB 聚合管道
linux下启动MongoDB 指令
查看服务器状态
[root@localhost bin]# systemctl status mongod.service
开机自启动
systemctl enable mongod.service
启动服务
systemctl start mongod.service
数据库
创建数据库
查看当前数据库
> db
test
切换数据库
进入数据库,如果没有会创建,但是插入数据才会再数据库列表中显示
> use examples switched to db examples
查看所有数据库
> show dbs admin 0.000GB config 0.000GB local 0.000GB
删除数据库
删除数据库
进入数据库,执行:
db.dropDatabase()
> show dbs admin 0.000GB config 0.000GB local 0.000GB test 0.000GB > use test switched to db test > db.dropDatabase() { "dropped" : "test", "ok" : 1 }
集合
创建集合
db.createCollection(name, options)
字段 | 类型 | 描述 |
---|---|---|
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
size | 数值 | (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 |
max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
db.createCollection("BBB") { "ok" : 1 } db.createCollection("bbb",{capped:true,size:5000,max:5000}) { "ok" : 1 }
查看集合
进入数据库,
> use test > show collections AAA BBB bbb ccc
删除集合
> db.ccc.drop() true > show collections AAA BBB bbb
文档
插入文档
save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。
db.COLLECTION_NAME.insert(document)
或
db.COLLECTION_NAME.save(document)
或
db.COLLECTION_NAME.insertOne()
或
db.COLLECTION_NAME.insertMany()
insert()
db.collection.insert( <document or array of documents>, { writeConcern: <document>, ordered: <boolean> } )
db.collection.insert({ "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 })
insertOne()
参数说明:
document:要写入的文档。
writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求
w: <number>,数据写入到number个节点才向用客户端确认
{w: 0} 对客户端的写入不需要发送任何确认,适用于性能要求高,但不关注正确性的场景
{w: 1} 默认的writeConcern,数据写入到Primary就向客户端发送确认
{w: "majority"} 数据写入到副本集大多数成员后向客户端发送确认,适用于对数据安全性要求比较高的场景,该选项会降低写入性能
j: <boolean> ,写入操作的journal持久化后才向客户端确认
默认为"{j: false},如果要求Primary写入持久化了才向客户端确认,则指定该选项为true
wtimeout: <millseconds>,写入超时时间,仅w的值大于1时有效。
当指定{w: }时,数据需要成功写入number个节点才算成功,如果写入过程中有节点故障,可能导致这个条件一直不能满足,从而一直不能向客户端发送确认结果,针对这种情况,客户端可设置wtimeout选项来指定超时时间,当写入过程持续超过该时间仍未结束,则认为写入失败
db.collection.insertOne( <document>, { writeConcern: <document> } ) > db.collection.insertOne( {"name":"wxh","age":23}, {writeConcern:{w:1,j:false,wtimeout:1000}} )
insertMany()
db.collection.insertMany( [ <document 1> , <document 2>, ... ], { writeConcern: <document>, ordered: <boolean> } )
db.collection.insertMany([ {"name":"wxh","age":23}, {"smoking":false,"glasses":true}])
更新文档
update() 方法
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
> db.collection.find().pretty() { "_id" : ObjectId("6216f6f0bfbdbcab2efdc46f"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } > db.collection.update( {"by":"菜鸟教程"}, {$set:{"url":"www.wxh.com"}}, {upsert:false,multi:true,writeConcent:{w:1,j:false,wtimeout:1000}}) > db.collection.find().pretty() { "_id" : ObjectId("6216f6f0bfbdbcab2efdc46f"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "www.wxh.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
删除文档
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
db.collection.remove( <query>, { justOne: <boolean>, writeConcern: <document> } )
删除部分文档
db.collection.remove( {"title" : "MongoDB 教程"}, { justOne: false } )
删除全部文档
db.collection.remove({})
查询文档
MongoDB 与 RDBMS Where 语句比较
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {: } |
db.col.find({"by":"菜鸟教程"}).pretty() |
where by = '菜鸟教程' |
小于 | {:{$lt:}} |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes < 50 |
小于或等于 | {:{$lte:}} |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes <= 50 |
大于 | {:{$gt:}} |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes > 50 |
大于或等于 | {:{$gte:}} |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes >= 50 |
不等于 | {:{$ne:}} |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes != 50 |
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
格式
db.collection.find(query, projection) > db.collection.find({},{_id:true}) { "_id" : ObjectId("621746c633498943fd27da03") } { "_id" : ObjectId("621746ea33498943fd27da04") } db.collection.find({},{_id:false}).pretty() { "name" : "wxh" } { "name" : "wxh", "AGE" : 34 }
AND 条件
> db.col.find({key1:value1, key2:value2}).pretty() > db.col.find({"by":"菜鸟教程", "title":"MongoDB 教程"}).pretty()
OR 条件
> db.col.find( { $or: [ {key1: value1}, {key2:value2} ] } ).pretty() > db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
AND 和 OR 联合使用
>db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
$type操作符
MongoDB 中可以使用的类型如下表所示
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | 已废弃。 |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1 . |
Max key | 127 |
获取集合field为String的数据
db.col.find({"title" : {$type : 2}}) 或 db.col.find({"title" : {$type : 'string'}})
Limit()与Skip()与sort()
skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit()。
{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "PHP 教程", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "php" ], "likes" : 200 } { "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Java 教程", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "java" ], "likes" : 150 } { "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb" ], "likes" : 100 }
limit()
db.COLLECTION_NAME.find().limit(NUMBER)
NUMBER: 从MongoDB中读取的记录条数。
> db.col.find({},{"title":1,_id:0}).limit(2) { "title" : "PHP 教程" } { "title" : "Java 教程" }
Skip()
还可以使用skip()方法来跳过指定数量的数据
> db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER) > db.col.find({},{"title":1,_id:0}).limit(1).skip(1) { "title" : "Java 教程" }
sort()
其中 1 为升序排列
而 -1 是用于降序排列
db.COLLECTION_NAME.find().sort({KEY:1}) > db.col.find({},{"title":1,_id:0}).sort({"likes":-1})
聚合
> db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 将值加入一个数组中,不会判断是否有重复的值。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
类似
select by_user, count(*) from mycol group by by_user
管道
$project:返回文档结构
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档
主要用于重命名、增加和删除字段
#结果中就只还有tilte和author > db.article.aggregate( { $project : { _id : 0 , title : 1 , author : 1 , }} ); #重命名字段名和子文档的字段名 db.article.aggregate({ $project : { title : 1 , page_views : "$pageViews" , bar : "$other.foo" }});
$match:过滤数据
$match: 筛选符合条件文档,作为下一阶段的输入
1.不能在$match操作符中使用$where表达式操作符。
2.$match尽量出现在管道的前面,这样可以提早过滤文档,加快聚合速度。
3.如果$match出现在最前面的话,可以使用索引来加快查询。
db.articles.aggregate( [ { $match : { score : { $gt : 70, $lte : 90 } } }, { $group: { _id: null, count: { $sum: 1 } } } ] );
$limit:限制返回文档数
$limit: 限制经过管道的文档数量
db.article.aggregate({ $limit : 5 });
$skip:跳过指定数量的文档
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档
db.article.aggregate({ $skip : 5 });
$unwind:拆分数组字段
$unwind: 将数组元素拆分为独立字段
> db.article.find() { "_id" : ObjectId("528751b0e7f3eea3d1412ce2"), "author" : "Jone", "title" : "Abook", "tags" : [ "good", "fun", "good" ] } > db.article.aggregate({$project:{author:1,title:1,tags:1}},{$unwind:"$tags"}) { "result" : [{ "_id" : bjectId("528751b0e7f3eea3d1412ce2"), "author" : "Jone", "title" : "A book", "tags" : "good" }, { "_id" : ObjectId("528751b0e7f3eea3d1412ce2"), "author" : "Jone", "title" : "A book", "tags" : "fun" }, { "_id" : ObjectId("528751b0e7f3eea3d1412ce2"), "author" : "Jone", "title" : "A book", "tags" : "good" }], "ok" : 1 }
$group:文档分组
$group:将集合中的文档分组,可用于统计结果
db.article.aggregate({ $group : { _id : "$author", docsPerAuthor : { $sum : 1 }, viewsPerAuthor : { $sum : "$pageViews" } } });
$sort:文档排序
$sort:将输入文档排序后输出
$sort出现在$limit之前的话,$sort只会对前$limit个文档进行操作
db.users.aggregate( { $sort : { age : -1, posts: 1 } });
关联关系
MongoDB 中的关系可以是:
1:1 (1对1)
1: N (1对多)
N: 1 (多对1)
N: N (多对多)
嵌入式关系
{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address": [ { "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }, { "building": "170 A, Acropolis Apt", "pincode": 456789, "city": "Chicago", "state": "Illinois" }] }
查询地址
> db.collection.findOne({"name":"Tom Benzamin"},{"address":1}) { "_id" : ObjectId("621c3e91d7dbca87f3020a34"), "address" : [ { "building" : "22 A, Indiana Apt", "pincode" : 123456, "city" : "Los Angeles", "state" : "California" }, { "building" : "170 A, Acropolis Apt", "pincode" : 456789, "city" : "Chicago", "state" : "Illinois" } ] }
{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address_ids": [ ObjectId("52ffc4a5d85242602e000000"), ObjectId("52ffc4a5d85242602e000001") ] } > var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1}) > var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})