JobPlus知识库 IT DBA 文章
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});  ---插入数据

[plain] 

  1. yoyo@rhel64-64bit:28000> db.foo.find()  
  2. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6252"), "name" : "yo0", "age" : 20, "sex" : 0 }  
  3. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6253"), "name" : "yo1", "age" : 21, "sex" : 1 }  
  4. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6254"), "name" : "yo2", "age" : 22, "sex" : 0 }  
  5. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6255"), "name" : "yo3", "age" : 23, "sex" : 1 }  
  6. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6256"), "name" : "yo4", "age" : 24, "sex" : 0 }  
  7. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6257"), "name" : "yo5", "age" : 25, "sex" : 1 }  
  8. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6258"), "name" : "yo6", "age" : 26, "sex" : 0 }  
  9. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6259"), "name" : "yo7", "age" : 27, "sex" : 1 }  
  10. { "_id" : ObjectId("5b2dff01b3d2ca4389ce625a"), "name" : "yo8", "age" : 28, "sex" : 0 }  
  11. { "_id" : ObjectId("5b2dff01b3d2ca4389ce625b"), "name" : "yo9", "age" : 29, "sex" : 1 }  
  12. { "_id" : ObjectId("5b2dff01b3d2ca4389ce625c"), "name" : "yo10", "age" : 30, "sex" : 0 }  
  13. { "_id" : ObjectId("5b2dff01b3d2ca4389ce625d"), "name" : "yo11", "age" : 31, "sex" : 1 }  
  14. { "_id" : ObjectId("5b2e00cfb3d2ca4389ce625e"), "name" : "yoyo", "addr" : "xyz", "pnum" : 133256 }  
  15. { "_id" : 111, "name" : "yoyo2", "addr" : "xyzz", "pnum" : 133556 }  
  16. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "foo1", "age" : 33, "score" : 99 }  
  17. { "_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()

[plain] 

  1. yoyo@rhel64-64bit:28000> db.foo.find()  
  2. { "_id" : ObjectId("5b2e00cfb3d2ca4389ce625e"), "name" : "yoyo", "addr" : "xyz", "pnum" : 133256 }  
  3. { "_id" : 111, "name" : "yoyo2", "addr" : "xyzz", "pnum" : 133556 }  

2.修改文档:

[plain] 

  1. yoyo@rhel64-64bit:28000> db.foo.update({score:99},{name:"fooo"})  
  2. 的结果是把文档  
  3. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "foo1", "age" : 33, "score" : 99 }  
  4. 修改变成  
  5. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo" }  
  6.   
  7. 如要局部字段值的修改,需要$inc和 $set:  
  8. db.foo.update({name:"fooo"},{$inc:{age:33}})的结果是:,$inc没有该字段会增加  
  9. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo" }  
  10. 修改变成:  
  11. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 33 }  
  12.   
  13. db.foo.update({name:"fooo"},{$set:{age:39}})的结果是:   
  14. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 33 }  
  15. 修改变成:  
  16. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }  
  17.   
  18. db.foo.update({name:"fooo"},{$inc:{age:33}},true,true)  
  19. --第一个true是如果匹配的文档不存在则插入一条新文档,第二true是否更新符合条件的  
  20. 多条记录,默认是只更新符合条件的第一个文档,是下面两个值的简写:  
  21. upsert: true  
  22. 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/

[plain] 

  1. 1>查询条件>, >=, <, <=, !=和linux的shell判断语句写法很像,对应是"$gt", "$gte", "$lt",  
  2.     "$lte", "$ne"  
  3.    db.collection.find( { field: { $gt: value1, $lt: value2 } } );  
  4.   
  5. yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:30}})  
  6. { "_id" : ObjectId("5b2dff01b3d2ca4389ce625c"), "name" : "yo10", "age" : 30, "sex" : 0 }  
  7. { "_id" : ObjectId("5b2dff01b3d2ca4389ce625d"), "name" : "yo11", "age" : 31, "sex" : 1 }  
  8. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }  

[plain] 

  1. 2>正则表达匹配的查询:  
  2. ---name:/^fo/类似SQL里面的like 'fo%',name:/fo/就是 like '%fo%',name:/fo$/就是like '%fo'  
  3. ---name:/^f.*o$/ 就是匹配f开头o结尾的name  
  4. yoyo@rhel64-64bit:28000> db.foo.find({name:/^fo/})   
  5. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }  
  6. { "_id" : ObjectId("5b2e14f729f8da4b472ef255"), "name" : "foo1", "age" : 33, "score" : 99 }  
  7.   
  8. yoyo@rhel64-64bit:28000> db.foo.find({name:/^f.*o$/})----f开头o结尾的name  
  9. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39}  

~~~~

[plain] 

  1. 3>and 和or匹配查询:  
  2. db.foo.find({$or:[{name:"fooo"},{age:33}]})  
  3.   
  4. yoyo@rhel64-64bit:28000> db.foo.find({$or:[{name:"fooo"},{age:33}]})  
  5. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }  
  6. { "_id" : ObjectId("5b2e14f729f8da4b472ef255"), "name" : "foo1", "age" : 33, "score" : 99 }  

[plain] 

  1. 4>in 和NotIn匹配查询:  
  2. db.foo.find({_id: { $in: [ 111, ObjectId("5b2e03d0b3d2ca4389ce625f") ] }})  
  3. yoyo@rhel64-64bit:28000> db.foo.find({_id: { $in: [ 111, ObjectId("5b2e03d0b3d2ca4389ce625f") ] }})  
  4. { "_id" : 111, "name" : "yoyo2", "addr" : "xyzz", "pnum" : 133556 }  
  5. { "_id" : ObjectId("5b2e03d0b3d2ca4389ce625f"), "name" : "fooo", "age" : 39 }  

[plain] 

  1. 5>只输出文档的某几个字段,类似select name,age from foo的搜索:  
  2. yoyo@rhel64-64bit:28000> db.foo.find({},{name:1,age:1,_id:0})  
  3.  .   .   .   .    .    .    .  
  4. { "name" : "yo11", "age" : 31 }  
  5. { "name" : "yoyo" }  
  6. { "name" : "yoyo2" }  
  7. { "name" : "foo1", "age" : 33 }  
  8.  只输出某个filed值存在的文档,如只列出age字段存在的文档:  
  9. db.foo.find({age:{$exists:true}})  

[plain] 

  1. 6>通过cursor里的forEach():  
  2. db.foo.find({age:{$lt:30}}).forEach(function(x) {print(x.name);})  
  3. yoyo@rhel64-64bit:28000> db.foo.find({age:{$lt:30}}).forEach(function(x) {print(x.name);})  
  4. yo0  
  5. yo1  
  6. yo2  
  7. yo3  
  8. 。。。  

[plain] 

  1. 7>sort,count,skip,limit  
  2. db.foo.find({age:{$gte:23,$lt:27}}).sort({name:-1}).skip(1).limit(2);  
  3. ---查询出age大于等23小于27的文档,并以name倒序排序  
  4. yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:23,$lt:27}}).sort({name:-1})   
  5. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6258"), "name" : "yo6", "age" : 26, "sex" : 0 }  
  6. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6257"), "name" : "yo5", "age" : 25, "sex" : 1 }  
  7. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6256"), "name" : "yo4", "age" : 24, "sex" : 0 }  
  8. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6255"), "name" : "yo3", "age" : 23, "sex" : 1 }  
  9. ---查询出age大于等23小于27的文档,并以name倒序排序,并跳过前1条,然后输出2条结果  
  10. yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:23,$lt:27}}).sort({name:-1}).skip(1).limit(2);  
  11. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6257"), "name" : "yo5", "age" : 25, "sex" : 1 }  
  12. { "_id" : ObjectId("5b2dff01b3d2ca4389ce6256"), "name" : "yo4", "age" : 24, "sex" : 0 }  
  13. ---查询出age大于等23小于27的文档,统计结果个数  
  14. yoyo@rhel64-64bit:28000> db.foo.find({age:{$gte:23,$lt:27}}).count()  
  15. 4  

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" } )         ----为所有字段建立全文索引

[plain] 

  1. yoyo@rhel64-64bit:28000> db.log.find()  
  2. { "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }  
  3. { "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test" }  
  4. { "_id" : ObjectId("5b2e4fcf29f8da4b472ef260"), "comments" : "abcdb cffc hh gefg", "desc" : "this is aa bb cc " }  
  5. db.log.createIndex( { comments: "text" } )  
  6.   
  7. 使用全文索引搜索:  
  8. yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"bb"}})----搜素comments字段包含bb  
  9. { "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }  
  10.   
  11. yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"aa cc"}})---搜素comments字段包含aa 或 cc  
  12. { "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test" }  
  13. { "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }  
  14.   
  15. yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"\"aa\" \"cc\""}})  ---搜索comments字段既包含aa又包含cc  
  16. { "_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"}})

[plain] 

  1. yoyo@rhel64-64bit:28000> db.log.find()  
  2. { "_id" : ObjectId("5b2e4f9729f8da4b472ef25e"), "comments" : "aa bb cc hh efg", "desc" : "this is first test" }  
  3. { "_id" : ObjectId("5b2e4fb529f8da4b472ef25f"), "comments" : "aa bcdb cffc hh gefg", "desc" : "this is aa cc second test" }  
  4. { "_id" : ObjectId("5b2e4fcf29f8da4b472ef260"), "comments" : "abcdb cffc hh gefg", "desc" : "this is aa bb cc " }  
  5. { "_id" : ObjectId("5b2e573029f8da4b472ef261"), "desc" : "this is aa" }  
  6.   
  7. ---搜索并以相似度排序:  
  8. yoyo@rhel64-64bit:28000> db.log.find({$text:{$search:"this is aa"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})  
  9. { "_id" : ObjectId("5b2e573029f8da4b472ef261"), "desc" : "this is aa", "score" : 1 }   -----相似度最高  
  10. { "_id" : ObjectId("5b2e4fcf29f8da4b472ef260"), "comments" : "abcdb cffc hh gefg", "desc" : "this is aa bb cc ", "score" : 0.6666666666666666 }  
  11. { "_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>执行计划和慢查询:

[plain]

  1. 执行计划:explain("executionStats")  
  2. db.foo.find({age:{$gte:26}}).hint({$natural:1 }).explain("executionStats")---hint({$natural:1 }) prevent搜索用任何索引  
  3. db.foo.find({age:{$gte:26}}).hint({age:1 }).explain("executionStats")  ---hint({age:1 })强制使用age字段搜索,hint对全文索引无效  
  4. 输出比较多:  
  5.     "stage" : "IXSCAN",  ---使用了索引扫描  
  6.     "keyPattern" : {  
  7.          "age" : 1   
  8.              },  
  9.     "indexName" : "age_1",---使用的索引名字  
  10.     "executionStats" : {  
  11.         "executionSuccess" : true,  
  12.         "nReturned" : 8,     ----一共返回的文档数  
  13.         "executionTimeMillis" : 0,----使用的时间毫秒  
  14.         "totalKeysExamined" : 8,  
  15.         "totalDocsExamined" : 8,  

[plain] 

  1. 慢查询:show profile  
  2. db.setProfilingLevel(2)  ---0是不开启,1记录慢查询,2记录所有命令  
  3. 执行:  
  4. db.foo.find({name:/o$/})  
  5. 查询:  
  6. db.system.profile.find({ns:"yoyo.foo"}).pretty(),输出和explain类似:  
  7.     "nreturned" : 4,  ---搜索结果返回了4个文档  
  8.     "responseLength" : 346,  
  9.     "protocol" : "op_msg",  
  10.     "millis" : 0,  
  11.     "planSummary" : "COLLSCAN", ---使用了全集合扫描  


如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持
428人赞 举报
分享到
用户评价(0)

暂无评价,你也可以发布评价哦:)

扫码APP

扫描使用APP

扫码使用

扫描使用小程序