MongoDB命令手册:
https://docs.mongodb.com/manual/reference/method/js-collection/
也可以mongo连接后,使用help查看:
help
db.help()
db.collections.help()
准备数据:
use yoyo ---创建数据库
db.createCollection("foo", {size: 20, capped: true, max:100}) ---创建定长集合
db.createCollection("foo") ---创建集合
for (var i = 0; i < 12; i++) db.foo.insert({name: "yo" + i, age: 20 + i, sex: i % 2}); ---插入数据
yoyo@rhel64-64bit:28000> db.foo.find()
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6252"), "name" : "yo0", "age" : 20, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6253"), "name" : "yo1", "age" : 21, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6254"), "name" : "yo2", "age" : 22, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6255"), "name" : "yo3", "age" : 23, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6256"), "name" : "yo4", "age" : 24, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6257"), "name" : "yo5", "age" : 25, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6258"), "name" : "yo6", "age" : 26, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6259"), "name" : "yo7", "age" : 27, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce625a"), "name" : "yo8", "age" : 28, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce625b"), "name" : "yo9", "age" : 29, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce625c"), "name" : "yo10", "age" : 30, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce625d"), "name" : "yo11", "age" : 31, "sex" : 1 }
{ "_id" : ObjectId("5b2e00cfb3d2ca4389ce625e"), "name" : "yoyo", "addr" : "xyz", "pnum" : 133256 }
{ "_id" : 111, "name" : "yoyo2", "addr" : "xyzz", "pnum" : 133556 }
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "foo1", "age" : 33, "score" : 99 }
{ "_id" : ObjectId("5b2e03f1b3d2ca4389ce6260"), "name" : "foo2", "age" : 35, "score" : 96 }
1.插入文档:
yoyo@rhel64-64bit:28000> db.foo.insert({name:"yoyo",addr:"xyz",pnum:133256})
WriteResult({ "nInserted" : 1 })
db.foo.insert({_id:111,name:"yoyo2",addr:"xyzz",pnum:133556}) ----可以手动指定_id值,但是必须唯一不可重复
查看:
db.foo.find().pretty()
yoyo@rhel64-64bit:28000> db.foo.find()
{ "_id" : ObjectId("5b2e00cfb3d2ca4389ce625e"), "name" : "yoyo", "addr" : "xyz", "pnum" : 133256 }
{ "_id" : 111, "name" : "yoyo2", "addr" : "xyzz", "pnum" : 133556 }
2.修改文档:
yoyo@rhel64-64bit:28000> db.foo.update({score:99},{name:"fooo"})
的结果是把文档
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "foo1", "age" : 33, "score" : 99 }
修改变成
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo" }
如要局部字段值的修改,需要$inc和 $set:
db.foo.update({name:"fooo"},{$inc:{age:33}})的结果是:,$inc没有该字段会增加
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo" }
修改变成:
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 33 }
db.foo.update({name:"fooo"},{$set:{age:39}})的结果是:
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 33 }
修改变成:
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }
db.foo.update({name:"fooo"},{$inc:{age:33}},true,true)
--第一个true是如果匹配的文档不存在则插入一条新文档,第二true是否更新符合条件的
多条记录,默认是只更新符合条件的第一个文档,是下面两个值的简写:
upsert: true
multi: true
3.删除文档:
删除集合中所有文档:
db.foo.drop()
db.foo.remove({})
删除符合条件的文档:
db.foo.remove({name:"foo2"},{justOne:true}) ---- justone表示只删符合条件的第一个文档
4.查询文档: 帮助--> db.collections.help()
https://docs.mongodb.com/manual/reference/method/db.collection.find/
1>查询条件>, >=, <, <=, !=和linux的shell判断语句写法很像,对应是"$gt", "$gte", "$lt",
"$lte", "$ne"
db.collection.find( { field: { $gt: value1, $lt: value2 } } );
yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:30}})
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce625c"), "name" : "yo10", "age" : 30, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce625d"), "name" : "yo11", "age" : 31, "sex" : 1 }
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }
2>正则表达匹配的查询:
---name:/^fo/类似SQL里面的like 'fo%',name:/fo/就是 like '%fo%',name:/fo$/就是like '%fo'
---name:/^f.*o$/ 就是匹配f开头o结尾的name,name:{$not:/^f.*/}匹配非f开头的name
yoyo@rhel64-64bit:28000> db.foo.find({name:/^fo/})
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }
{ "_id" : ObjectId("5b2e14f729f8da4b472ef255"), "name" : "foo1", "age" : 33, "score" : 99 }
yoyo@rhel64-64bit:28000> db.foo.find({name:/^f.*o$/})----f开头o结尾的name
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39}
3>and 和or匹配查询:
db.foo.find({$or:[{name:"fooo"},{age:33}]})
yoyo@rhel64-64bit:28000> db.foo.find({$or:[{name:"fooo"},{age:33}]})
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }
{ "_id" : ObjectId("5b2e14f729f8da4b472ef255"), "name" : "foo1", "age" : 33, "score" : 99 }
4>in 和NotIn匹配查询:
db.foo.find({_id: { $in: [ 111, ObjectId("5b2e03d0b3d2ca4389ce625f") ] }})
yoyo@rhel64-64bit:28000> db.foo.find({_id: { $in: [ 111, ObjectId("5b2e03d0b3d2ca4389ce625f") ] }})
{ "_id" : 111, "name" : "yoyo2", "addr" : "xyzz", "pnum" : 133556 }
{ "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }
5>只输出文档的某几个字段,类似select name,age from foo的搜索:
yoyo@rhel64-64bit:28000> db.foo.find({},{name:1,age:1,_id:0})
. . . . . . .
{ "name" : "yo11", "age" : 31 }
{ "name" : "yoyo" }
{ "name" : "yoyo2" }
{ "name" : "foo1", "age" : 33 }
只输出某个field值存在的文档,如只列出age字段存在的文档:
db.foo.find({age:{$exists:true}})
db.foo.find({name:{$not:/^y.*/,$exists:true}})---输出name不是以y开头,而且name字段存在的文档
6>通过cursor:
for(var c=db.foo.find();c.hasNext();){printjson(c.next())}
db.foo.find().forEach(printjson)
db.foo.find({age:{$lt:30}}).forEach(function(x) {print(x.name);})
yoyo@rhel64-64bit:28000> db.foo.find({age:{$lt:30}}).forEach(function(x) {print(x.name);})
yo0
yo1
yo2
yo3
。。。
7>sort,count,skip,limit
db.foo.find({age:{$gte:23,$lt:27}}).sort({name:-1}).skip(1).limit(2);
---查询出age大于等23小于27的文档,并以name倒序排序
yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:23,$lt:27}}).sort({name:-1})
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6258"), "name" : "yo6", "age" : 26, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6257"), "name" : "yo5", "age" : 25, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6256"), "name" : "yo4", "age" : 24, "sex" : 0 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6255"), "name" : "yo3", "age" : 23, "sex" : 1 }
---查询出age大于等23小于27的文档,并以name倒序排序,并跳过前1条,然后输出2条结果
yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:23,$lt:27}}).sort({name:-1}).skip(1).limit(2);
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6257"), "name" : "yo5", "age" : 25, "sex" : 1 }
{ "_id" : ObjectId("5b2dff01b3d2ca4389ce6256"), "name" : "yo4", "age" : 24, "sex" : 0 }
---查询出age大于等23小于27的文档,统计结果个数
yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:23,$lt:27}}).count()
4
8>数组的查询:
yooo:SECONDARY> db.foo.find({},{_id:0}) ---foo集合的所有文档如下:
{ "x" : 1, "y" : 1 }
{ "x" : [ 2, 3 ], "y" : [ 1, 5 ], "z" : [ { "z1" : 11 }, { "z2" : 22 } ] }
{ "z" : { "z1" : 11, "z2" : 22 } }
yooo:SECONDARY> db.foo.find({"z.z1":11},{_id:0}) ---查询z字段里面z1为11的文档
{ "x" : [ 2, 3 ], "y" : [ 1, 5 ], "z" : [ { "z1" : 11 }, { "z2" : 22 } ] }
{ "z" : { "z1" : 11, "z2" : 22 } }
yooo:SECONDARY> db.foo.find({"x.1":3},{_id:0}) ----查询x字段的数组1,值为3的文档
{ "x" : [ 2, 3 ], "y" : [ 1, 5 ], "z" : [ { "z1" : 11 }, { "z2" : 22 } ] }
yooo:SECONDARY> db.foo.find({"z.0.z1":11},{_id:0})----查询z字段,数组0里面z1字段值为11的文档
{ "x" : [ 2, 3 ], "y" : [ 1, 5 ], "z" : [ { "z1" : 11 }, { "z2" : 22 } ]
5.索引:https://docs.mongodb.com/manual/indexes/index.html
1>创建索引:
yoyo@rhel64-64bit:28000> db.foo.createIndex({age:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
查看index:
yoyo@rhel64-64bit:28000> db.foo.getIndexes()
删除index:
db.foo.dropIndex("createdat_1")
2>创建索引的其他属性:
给索引起个名字:name
db.foo.createIndex({age:1},{name:yoidx})
唯一索引:unique
db.foo.createIndex({age:1},{unique:true})
部分索引:partial 如下只给年龄大于25的文档的name filed建立索引
db.foo.createIndex({name:1},{partialFilterExpression: {age: {$gt:25}}})
稀疏索引:索引只包含有索引字段的文档的条目,跳过索引键不存在的文档
db.foo.createIndex({age:1},{sparse:true})
TTL索引:指定文档多长时间过期
第一种:文档创建后多久过期:
db.foo.createIndex( { createdAt: 1 }, { expireAfterSeconds: 10 } )
文档创建后10s后被删除:
db.foo.insert({createdAt:new Date(),name:"yoo",desc:"xyzz"})
第二种:指定具体的过期时间:
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
db.log_events.insert( {
"expireAt": new Date('July 22, 2018 14:00:00'), ----指定文档的过期时间
"logEvent": 2,"logMessage": "Success!"
} )
TTL索引限制:
不支持复合索引
不支持定长集合
索引字段需要为ISODATE时间类型
3>全文索引:一个集合只能有一个全文索引A collection can have at most one text index.
db.collection.createIndex( { comments: "text" } ) ---为comment字段建立全文索引
db.collection.createIndex( { "$**": "text" } ) ----为所有字段建立全文索引
yoyo@rhel64-64bit:28000> db.log.find()
{ "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }
{ "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test" }
{ "_id" : ObjectId("5b2e4fcf29f8da4b472ef260"), "comments" : "abcdb cffc hh gefg", "desc" : "this is aa bb cc " }
db.log.createIndex( { comments: "text" } )
使用全文索引搜索:
yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"bb"}})----搜素comments字段包含bb
{ "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }
yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"aa cc"}})---搜素comments字段包含aa 或 cc
{ "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test" }
{ "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }
yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"\"aa\" \"cc\""}}) ---搜索comments字段既包含aa又包含cc
{ "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }
全文索引相似度,搜索排序:
db.log.dropIndex("comments_text")
db.log.createIndex( { desc: "text" } )
db.log.insert({desc:"this is aa"})
db.log.find({$text:{$search:"this is aa"}},{score:{$meta:"textScore"}})
yoyo@rhel64-64bit:28000> db.log.find()
{ "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }
{ "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test" }
{ "_id" : ObjectId("5b2e4fcf29f8da4b472ef260"), "comments" : "abcdb cffc hh gefg", "desc" : "this is aa bb cc " }
{ "_id" : ObjectId("5b2e573029f8da4b472ef261"), "desc" : "this is aa" }
---搜索并以相似度排序:
yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"this is aa"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
{ "_id" : ObjectId("5b2e573029f8da4b472ef261"), "desc" : "this is aa", "score" : 1 } -----相似度最高
{ "_id" : ObjectId("5b2e4fcf29f8da4b472ef260"), "comments" : "abcdb cffc hh gefg", "desc" : "this is aa bb cc ", "score" : 0.6666666666666666 }
{ "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test", "score" : 0.625 }
4>2d索引:主要适用于地理位置查找
https://docs.mongodb.com/manual/core/2d/
创建:db.collection.createIndex( { <location field> : "2d" } ,
查询:db.<collection>.find( { <location field> :
{ $geoWithin :
{ $box|$polygon|$center : <coordinates>
} } } )
5>执行计划和慢查询:
执行计划:explain("executionStats")
db.foo.find({age:{$gte:26}}).hint({$natural:1 }).explain("executionStats")---hint({$natural:1 }) prevent搜索用任何索引
db.foo.find({age:{$gte:26}}).hint({age:1 }).explain("executionStats") ---hint({age:1 })强制使用age字段搜索,hint对全文索引无效
输出比较多:
"stage" : "IXSCAN", ---使用了索引扫描
"keyPattern" : {
"age" : 1
},
"indexName" : "age_1",---使用的索引名字
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 8, ----一共返回的文档数
"executionTimeMillis" : 0,----使用的时间毫秒
"totalKeysExamined" : 8,
"totalDocsExamined" : 8,
慢查询:show profile
db.setProfilingLevel(2) ---0是不开启,1记录慢查询,2记录所有命令
执行:
db.foo.find({name:/o$/})
查询:
db.system.profile.find({ns:"yoyo.foo"}).pretty(),输出和explain类似:
"nreturned" : 4, ---搜索结果返回了4个文档
"responseLength" : 346,
"protocol" : "op_msg",
"millis" : 0,
"planSummary" : "COLLSCAN", ---使用了全集合扫描