MongoDB2:增删改查命令和索引

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", ---使用了全集合扫描


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值