MongoDB Shell 命令
1、数据库命令
# 显示所有数据库
show dbs

# 显示当前使用的数据库
db

# 切换到local数据库,如果不存在local数据库,则创建
use local

# 删除当前数据库
db.dropDatabase

2、对数据库集合的操作
# 显示当前数据库的所有集合
show collections

# 在当前数据库中创建一个集合worker
db.createCollection("worker")

# 删除当前数据库中的worker集合
db.worker.drop()

3、编辑集合的数据
# 往当前数据库的worker集合中插入一条数据,如果不存在worker集合,则创建
db.worker.insert(
{
  "name": "fanyangyang",
  "age": 24
}
)

# 往当前数据库的worker集合中插入两条数据,如果不存在worker集合,则创建
db.worker.insert(
[
  {
    "name": "chengya",
    "age": 25
  },
  {
    "name": "quanzhisheng",
    "hobby": [
      "first",
      "second"
    ]
  }
]
)

# 查找worker集合中name为chengya的文档,并用{"name":"chengya","score":54}作为新文档,替换旧文档
# 没有匹配到则不更新也不新增
db.worker.replaceOne(
{"name": "chengya"},
{"name": "chengya", "score": 54}
) 

# 查找worker集合中name为wangfang的文档,并用{"name":"wangfang","score":54}作为新文档,替换旧文档,没有匹配到则新增
# upsert参数设置为true时,如果没有匹配到符合条件的文档,则新增
# 在更新数据库之后,生成了一个对象wangfang,这个对象的内容即为此次更新数据库的结果,
# 例如匹配数据条数,修改数据条数,插入数据的id等
var wangfang = db.worker.replaceOne({"name":"wangfang"},{"name":"wangfang","score":54},{"upsert":true})

# 更新worker集合的数据,
# upsert 设置为true,表示未匹配到符合条件的数据,则新增
# multi 设置为true,表示匹配到多个符合条件的数据时,更新所有数据;默认false,即只更新符合要求的第一条数据
# key-value,key可以省略引号,value的引号不可以省略。
# update与replaceOne不同,update可以只修改指定的字段,未指定的字段不做任何处理;replaceOne将匹配到的数据完全替换。
db.worker.update({name:"zhangjian"},{$set:{name:"lihui",age:28}},{upsert:true,multi:true})

# 将clearTime设置为当前时间
# 注意:如果 $set 没有写,那么update函数的作用就和replaceOne函数一样了,将会把原数据整条替换,而不是只对指定字段进行更新。
db.worker.update({name:"majinqiao"},{$set:{clearTime:new Date()}})

# 删除集合中的文档
db.worker.deleteOne({name:"lihui"})
db.worker.deleteMany({name:"lihui"})
db.worker.deleteMany({})
4、查询
# 查询worker集合中name属性是"majinqiao"的数据
# pretty函数 ,以格式化的方式显示查询结果
db.worker.find({name:"majinqiao"}).pretty()

# or查询 name = "majinqiao" or score = 54
db.worker.find({$or:[{name:"majinqiao"},{score:54}]}).pretty()

# or查询  age < 30 or age > 50
db.worker.find({$or:[{age:{$lt:30}},{age:{$gt:50}}]})

# or查询  age <= 30 or age => 50
db.worker.find({$or:[{age:{$lte:30}},{age:{$gte:50}}]})

# and查询  age != 30 and name != 'chengya'
db.worker.find({age:{$ne:30},age:{$ne:50}})

# and查询,name = "majinqiao" and age = 36
db.worker.find({name:"majinqiao",age:36}).pretty()

# 查找name字段为字符串的数据
db.worker.find({name:{$type:"string"}})

# 限制查询结果条数为2条
db.worker.find({name:"zhangjian"}).limit(2)

# province字段正序排列,city_age字段倒序排列
db.city.find().sort({province:1,city_age:-1})

# 当limit,skip,sort同时出现时,逻辑顺序为sort,skip,limit
db.worker.find({name:"zhangjian"}).limit(2).skip(1).sort({score:1})

# 查询city集合中存在history字段,且history的值是null的数据
db.city.find({history:{$in:[null],$exists:true}})

# select _id,city_name as cityName from city where city_name = 'jingzhou' and city_age >= 10
# _id 是默认查询的,如果想不返回这个字段, _id:0 即可
db.city.find({city_name:"jingzhou",city_age:{$gte:10}},{cityName:"$city_name"})

5、索引

# 为集合worker创建一个联合索引,name升序,age降序,设置索引名字为worker_index
db.worker.createIndex({name:1,age:-1},{name:"worker_index"})

# 查看集合的索引
db.worker.getIndexes()

# 查看集合索引的大小
db.worker.totalIndexSize()

# 删除集合的索引,索引名为name_1_age_-1
db.worker.dropIndex("name_1_age_-1")

6、查询覆盖索引

mongoDB查询分析较常使用的函数是 .explain("executionStats") ,例如
db.city.find({city_age:{$gt:100}}).explain("executionStats")
此函数的输出结果中:
queryPlanner.winningPlan.inputStage.stage 显示为 IXSCAN,表示使用了索引扫描;若显示为COLLSCAN,则表示使用了集合扫描
executionStats.nReturned 显示为 3,表示匹配查询并返回的文档数目为 3
executionStats.totalKeysExamined 显示为 3,表示 MongoDB 扫描了 3 个索引条目
executionStats.totalDocsExamined 显示为 3,表示 MongoDB 扫描了 3 个文档

如何才能是查询覆盖索引:
1、遵循最左匹配原则
首先建立一个索引
db.city.createIndex({city_name:1,city_age:1},{name:"city_name_age_index"})
然后分别做以下查询:
db.city.find({city_name:"wuhan",city_age:{$gt:300,$lt:400}}).explain("executionStats")
查询使用了索引。
然后把查询条件的顺序调换一下
db.city.find({city_age:{$gt:300,$lt:400}},city_name:"wuhan").explain("executionStats")
查询使用了索引。
db.city.find({city_name:"wuhan"}).explain("executionStats")
查询使用了索引
db.city.find({city_age:{$gt:300,$lt:400}}).explain("executionStats")
查询没有走索引,而是进行了集合扫描。
那么,当查询条件的部分字段不是索引中的字段时,又会怎样呢?
首先,做如下查询,这里查询条件中的province就是不存在于索引中的
db.city.find({city_name:"wuhan",province:"hubei"}).explain("executionStats")
结果发现居然使用了索引。
接下来,再尝试这个查询
db.city.find({city_age:{$gt:300,$lt:400},province:"hubei"}).explain("executionStats")
发现这个查询是没有使用索引的,而是采用了集合扫描的方式。
这是因为city_age是我们索引中的第二个字段,而索引中的第一个字段city_name并没有出现在查询条件中,所以查询没有覆盖索引。
因此,我们可以得出一个结论,mongo的索引遵循最左匹配原则。

7、聚合

# select province,count(*) as cityNum from city group by province;
db.city.aggregate([{$group:{_id:"$province",cityNum:{$sum:1}}}])

# select province,sum(city_age) as cityAge from city group by province;
db.city.aggregate([{$group:{_id:"$province",cityAge:{$sum:"$city_age"}}}])

# 按照province分组,求city_age的平均值
db.city.aggregate({$group:{_id:"$province",avgAge:{$avg:"$city_age"}}})

# 按照province分组,求city_age的最小值
db.city.aggregate({$group:{_id:"$province",minAge:{$min:"$city_age"}}})

# select province,sum(city_age) from city group by province where province = 'hubei' ;
# 此处$match 相当于sql中的where关键字,注意分组后province的别名是 _id
# 因此,此处如果写成 {$match:{province:"hubei"}} 是查询不到结果的
db.city.aggregate([{$group:{_id:"$province",sumAge:{$sum:"$city_age"}}},{$match:{_id:"hubei"}}])
# db.city.aggregate([{$match:{province:"hubei"}},{$group:{_id:"$province",sumAge:{$sum:"$city_age"}}}])
# 这又是可以的,这种方式是先按条件筛选,然后再聚合的

# 计算city集合中所有数据的city_age的总和
db.city.aggregate([{$group:{_id:null,sumAge:{$sum:"$city_age"}}}])

# $project只输出指定的字段,_id是默认会输出的,_id:0 表示不输出 _id
db.city.aggregate([{$match:{history:{$in:[null],$exists:true}}},{$project:{_id:0,city_name:1,province:1}}])

# worker集合的address字段是数组类型, $unwind将address数组拆分为元素,然后将这些元素与其他字段一起逐条输出
db.worker.aggregate([{$unwind:"$address"}])

# select count(*) as city_count from city where province in ('hubei','hunan');
db.city.aggregate([{$match:{province:{$in:["hubei","hunan"]}}},{$count:"city_count"}])

# 我的集合文档是
# { "_id" : ObjectId("60c48afadb603930d40f2492"), "city_name" : "changsha", "city_age" : 106, "province" : "hunan", "create_time" : ISODate("2021-06-14T11:40:00Z"), "history" : null }
db.city.aggregate([{$match:{city_name:"changsha"}},{$project:{city_name:1,"create_year":{$year:"$create_time"},"create_month":{$month:"$create_time"},"create_day":{$dayOfMonth:"$create_time"}}}])
# 查询结果是
# { "_id" : ObjectId("60c48afadb603930d40f2492"), "city_name" : "changsha", "create_year" : 2021, "create_month" : 6, "create_day" : 14 }

# 只取特定的几个字段,并使用别名返回
db.city.aggregate([{$project:{_id:0,cityName:"$city_name",createTime:"$create_time"}}])

# 查询   2021-06-01 <= create_time <= 2021-08-31
db.city.find({create_time:{$gte:new Date(2021,5,1)},create_time:{$lt:new Date(2021,8,1)}})

# new Date(2021,6,6) 实际是 2021-07-06 00:00:00

8、引用

# 首先,插入数据 
# 还有一个 $db可选参数,指定数据库名称,如果不设置,默认当前库
db.worker.insert({worker_name:"xumingkai",address:{$ref:"city",$id:ObjectId("60c48e76db603930d40f249f")}})

# 然后,关联查询
var worker = db.worker.findOne({worker_name:"xumingkai"})
var address = worker.address
db[address.$ref].findOne({_id:(address.$id)})
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐