一、MongoDB的基本语法使用

1)对库的增删查

show dbs    # 显示所有的库

use admin   # 切换到管理员库

# db是默认的全局变量
在哪个库下,db的值就是当前库

mongo中没有创建库,和表的概念
直接切换库 use db1   (无论有没有该库)
空库,空表不显示

===================================
help
数据库
    增
        use db1 # 有则切换,无则新增
    查
        show dbs    # 查看所有
        db # 当前
    删
        db.dropDatabase()

2)对集合(表)的增删查

增
    db.user
    db.user.info
    db.user.auth
查看(显示所有的表)
    show collections
    show tables
删除
    db.user.drop()     # 删除user表

3.1)对文档(表中的一条数据)的增加

db.user.insert({"_id":1,"name":"dasb"})
示例(唯一id)
> db.user.insert({"a":1})
WriteResult({ "nInserted" : 1 })
> db.user.find()
{ "_id" : ObjectId("5c05deda76533a68c742cb54"), "a" : 1 }
> db.user2.find()

3.2)对文档的单条数据和多条数据的增加(赋予变量的形式)

  数据准备

#1、没有指定_id则默认ObjectId,_id不能重复,且在插入后不可变

#2、插入单条
user0={
    "name":"egon",
    "age":10,
    'hobbies':['music','read','dancing'],
    'addr':{
        'country':'China',
        'city':'BJ'
    }
}

db.test.insert(user0)
db.test.find()

#3、插入多条
user1={
    "_id":1,
    "name":"alex",
    "age":10,
    'hobbies':['music','read','dancing'],
    'addr':{
        'country':'China',
        'city':'weifang'
    }
}

user2={
    "_id":2,
    "name":"wupeiqi",
    "age":20,
    'hobbies':['music','read','run'],
    'addr':{
        'country':'China',
        'city':'hebei'
    }
}


user3={
    "_id":3,
    "name":"yuanhao",
    "age":30,
    'hobbies':['music','drink'],
    'addr':{
        'country':'China',
        'city':'heibei'
    }
}

user4={
    "_id":4,
    "name":"jingliyang",
    "age":40,
    'hobbies':['music','read','dancing','tea'],
    'addr':{
        'country':'China',
        'city':'BJ'
    }
}

user5={
    "_id":5,
    "name":"jinxin",
    "age":50,
    'hobbies':['music','read',],
    'addr':{
        'country':'China',
        'city':'henan'
    }
}
db.user.insertMany([user1,user2,user3,user4,user5])

单条插入与多条插入

二、对文档(表中的一条数据)的查看

1)最基本的查看

db.user.find()
db.user.find().pretty()      # 格式化查看
db.user.findOne()      # 查看一条(第一条)
db.user.find().count()  # 获取数量
db.user.find({"_id":2})     # 指定条件查看id=2的。
db.user.find({"b":null})    # b的值为null和没有b的都会被查找到

2)比较运算的查看

db.user.find({"_id":{"$ne":2}})     # 指定条件查看id不等于2的
db.user.find({"_id":{"$gt":2}})     # 大于2
db.user.find({"_id":{"$lt":2}})     # 小于2
db.user.find({"_id":{"$gte":2}})    # 大于等于2
db.user.find({"_id":{"$lte":2}})    # 小于等于2
db.user.find({"_id":{"$mod":[2,1]}})    # 找到id除以2,余数为1的

3)逻辑运算的查看 $and,$or, $not

db.user.find({"_id":{"$gte":3,"$lte":4}})   # 找id大于等于3并且小于等于4的
多个条件的第一种写法
db.user.find({                              # 找到id大于等于3并且小于等于4的,并且年纪大于等于40的
    "_id":{"$gte":3,"$lte":4},
    "age":{"$gte":40}
})
多个条件的第二种写法
db.user.find({"$and":[              # $and 去进行条件连接
{"_id":{"$gte":3,"$lte":4}},        # 条件一
{"age":{"$gte":40}}                 # 条件二
]})
--------$or
db.user.find({"$or":[              # $or 去进行条件连接
{"_id":{"$lte":1,"$gte":0}},        # 条件一
{"age":{"$gte":40}}                 # 条件二
]})
--------$not 取反
db.user.find({
"_id":{"$not":{"$mod":[2,1]}}
})

4)成员运算,$in,$nin

db.user.find({"name":{"$in":["dasb","sb"]}})        # 找到名字有这些的条件
db.user.find({"name":{"$nin":["dasb","sb"]}})       # 找到名字没有这些的条件

5)正则匹配

db.user.find({
"name":/^jin.*?(g|n)$/i     #以jin开头,g和n结尾 ,i是忽略大小写
})

6)查看指定字段。显示条件,0为不显示,1为显示

db.user.find({
    "name":/^jin.*?(g|n)$/i     # 插定查询条件
},
{
    "_id":0,
    "name":1,
    "age":1
}
)

7)对数据相关操作,value为列表,和嵌套字典等

db.user.find({"hobbies":"dancing"})     # 查询爱好有跳舞的
db.user.find({
    "hobbies":{"$all":["dancing","tea"]}    # 查询既有跳舞和喝茶爱好的
)
db.user.find({"hobbies.2":"dancing"})       # 查询第三个爱好是跳舞的
db.user.find(
{},
{
    "_id":0,
    "name":0,
    "age":0,
    "hobbies":{"$slice":-2}     # 切片,查询爱好为后面2个的数据
}
)
db.user.find(
{},
{
    "_id":0,
    "name":0,
    "age":0,
    "hobbies":{"$slice":[1,2]}     # 切片,查询第2个和第3个。数据,0,1,2
}
)
db.user.find(
{},
{
    "_id":0,
    "name":0,
    "age":0,
    "hobbies":{"$slice":2}     # 切片,查询爱好为后前面2个的数据
}
db.user.find({"addr.country":"China"})   # 查询嵌入型文档
如:{"addr":{"country":"China","city":"BJ"}}

8)排序查找sort,限制查询limit,跳过查询skip

db.user.find()  # 默认按照id排序(升序)
db.user.find().sort({"_id":1})         # 1,按照id排序(升序)
db.user.find().sort({"_id":-1})        # -1,按照id排序(降序)
-------------------------------------------
db.user.find.limit(2)   # 只查前面2条
db.user.find.limit(2).skip(0)   # 跳过0个,取2个
db.user.find.limit(2).skip(2)   # 跳过2个,取2个

二、对文档(表中的一条数据)的修改

1)save方法(有则覆盖,无则新增)

db.user.save({"_id":1,"z":6})   # 如果有相同id则覆盖,没有新增(sava方法,如果不指定id,系统则随意造id,新增)

2.1)文档改的语法

db.table.update(
    条件,
    其他字段,
    其他参数
)

2.2)文档修改

db.table.update(
    {},                 # 不指定条件指查询全部
    {"age":11},         # 将年纪修改为11
    {
        "multi":true,   # 默认为falue,只修改第一条。true,修改所有
        "upsert":true   # 如果查询不到,则增加该条
    }
)
错误示例
db.user.update(
    {"name":"dasb"},    # 查询到这个条件
    {"age":23,"name":"xsb}  # 将符合条件的原有的数据覆盖成了这个结果
)
正确示例(局部修改)
db.user.update(
    {"name":"dasb"},
    {"$set":{"age":23,"name":"xsb}}
)

db.cmdb_instance.updateMany({userName:"daxhxcmdb"}, {$set:{userName:"deaosi"}});

3)对字段中的value(整数)的加减。$inc方法

db.user.update(
    {},
    {"$inc":"age":1}    # 将第一条的年纪加1;"age":-5,则减5
)

4)$push 和$addToSet

4.1)$push ,类似于列表的append方法。$addToSet 避免添加重复的内容

db.user.update(
    {"name":"dasb"},
    {"$push":{"hobbies":"tangtou"}},
    {"multi":true}
)
#  $push+$each 可连续append多个值
db.user.update(
    {"name":"dasb"},
    {"$push":{"hobbies":{"$each":["纹身","抽烟"}}},
    {"multi":true}
)

# $addToSet     避免添加重复的内容
db.user.update(
    {},
    {"$addToSet":"numbers":{"$each":[1,2,3,2,3]}},
)

三、对文档(表中的数据)的删除

1)删除字段 $unset

db.user.update(
    {"name":"dasb"},
    {"$unset":{"age":""}}       # 删除该字段。$unset,字段为空
)

2) $pop 删除字段列表值,可模拟队列

db.user.update(
    {"name":"dasb"},
    {"$pop":{"hobbies":-1}}       # 删除该字段里面的列表的第一个,从头删-1,从尾删1
)

3)$pull ,按照条件删除

db.user.update(
    {"name":"yuaohao"},
    {"$pull":{"hobbbies":"纹身"}},
    {"multi":true}
)

四、对文档删除(整体数据删除)

db.user.deleteOne({"_id":{"$gte":3}})   # 删除大于等于3的,找到的第一条
db.user.deleteMany({"_id":{"$gte":3}})  # 删除多条
db.user.deleteMany({})      # 删除全部

五、深入查询

数据准备阶段

# pip install pymongo
from pymongo import MongoClient
import datetime

client=MongoClient('mongodb://root:123@localhost:27017')
table=client['db1']['emp']
# table.drop()

l=[
('egon','male',18,'20170301','老男孩驻沙河办事处外交大使',7300.33,401,1), #以下是教学部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龙','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3)
]

for n,item in enumerate(l):
    d={
        "_id":n,
        'name':item[0],
        'sex':item[1],
        'age':item[2],
        'hire_date':datetime.datetime.strptime(item[3],'%Y%m%d'),
        'post':item[4],
        'salary':item[5]
    }
    table.save(d)

数据准备

1)聚合操作。聚合aggregate:过滤 $match,分组$group

过滤 $match
    在mysql中:select * from db1.emp where age > 20;
    db.emp.aggregate({"$match":{"age":{"$gt":20}}})
分组 $group
    在mysql中:select * from db1.emp where age > 20 group by post;
    db.emp.aggregate(
        {"$match":{"age":{"$gt":20}}},
        {"$group":{"_id":"$post"}}  # _id分组依据。注意不是默认的表的_id区分。$post,取post字段的value值
    )
    再算出平均工资
    db.emp.aggregate(
        {"$match":{"age":{"$gt":20}}},
        {"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}}
    )
    # 再过滤出平均工资大于10000的
    db.emp.aggregate(
        {"$match":{"age":{"$gt":20}}},
        {"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}},
        {"$match":{"avg_salary":{"$gt":10000}}}
        )

2)投射操作 {"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表达式"}}

# 显示需要的字段。mysql中,select age,salary from table;
db.emp.aggregate(
    {"$project":{"_id":1,"name":1,"post":1,"salary":1}}
)
# 映射,将月薪映射成年薪,$multiply 相乘
db.emp.aggregate(
    {"$project":{"_id":1,"name":1,"post":1,"annual_salary":{"$multiply":[12,"$salary"]}}}
)
# 计算每个部门的平均年薪
db.emp.aggregate(
    {"$project":{"_id":1,"name":1,"post":1,"annual_salary":{"$multiply":[12,"$salary"]}}},
    {"$group":{"_id":"$post","平均年薪":{"$avg":"$annual_salary"}}}
)
# 过滤出部门平均年薪大于1000000的
db.emp.aggregate(
    {"$project":{"_id":1,"name":1,"post":1,"annual_salary":{"$multiply":[12,"$salary"]}}},
    {"$group":{"_id":"$post","平均年薪":{"$avg":"$annual_salary"}}},
    {"$match":{"平均年薪":{"$gt":1000000}}}
)
# 再使用投射
db.emp.aggregate(
    {"$project":{"_id":1,"name":1,"post":1,"annual_salary":{"$multiply":[12,"$salary"]}}},
    {"$group":{"_id":"$post","平均年薪":{"$avg":"$annual_salary"}}},
    {"$match":{"平均年薪":{"$gt":1000000}}},
    {"$project":{"部门名":"$_id","平均年薪":1,"_id":0}}
)

3)时间操作。$subtract 相减,现在时间,new Date()

# 计算出工作时间,$subtract 相减,现在时间,new Date(),
db.emp.aggregate(
    {"$project":{"_id":0,"name":1,"hire_period":{"$subtract":[new Date(),"$hire_date"]}}}
)
# 时间中2017-10-12,过滤出年
db.emp.aggregate(
    {"$project":{"_id":0,"name":1,"hire_year":{"$year":"$hire_date"}}}
)

4)将字符串变为大写,字符串加后缀,取字符串字节

# 将名字变为大写
db.emp.aggregate(
    {"$project":{"_id":0,"new_name":{"$toUpper":"$name"}}}
)
# 过滤出除了egon的,其他的名字后缀都加 _SB
db.emp.aggregate(
    {"$match":{"name":{"$ne":"egon"}}},
    {"$project":{"_id":0,"new_name":{"$concat":["$name","_SB"]}}}
)
# 取出名字的前3个字节,是以utf8做的编码。必须是以3的倍数取值
db.emp.aggregate(
    {"$match":{"name":{"$ne":"egon"}}},
    {"$project":{"_id":0,"new_name":{"$substr":["$name",0,3]}}}
)

5)排序 $sort 、限制$limit 、跳过$skip,随机 sample

db.emp.aggregate(
    {"$match":{"name":{"$ne":"egon"}}},
    {"$project":{"_id":1,"new_name":{"$substr":["$name",0,3]}}}
    {"$sort":{"age":1,"_id":-1}},     # 1,从小到大;-1,从大到小
    {"$skip":5},        # 跳过5条
    {"$limit":5}        # 再查找5条
)
补充,随机取3
db.emp.aggragate({"sample":{"size":3}})

6) 模糊查询

db.cmdb_instance.find({"instance_id":{"$regex": /ins/}})
db.cmdb_instance.find({"instance_id":{"$regex": /ins/,"$options":"ins"}})
db.cmdb_instance.find({"instance_id":{"$options": ins}})

7)综合练习

db.emp.aggregate(
    {"$group":{
        "_id":"$post",
        "max_age":{"$max":"$age"},
        "min_id":{"$min":"$_id"},
        "avg_salary":{"$avg":"$salary"},
        "sum_salary":{"$sum":"$salary"},
        "count":{"$sum":1},
        "names":{"$push":"$name"}
    }}
)

aggregate综合 

mongodb转义 mongodb语法_mongodb转义

 

mongodb转义 mongodb语法_ci_02

7)解决查找慢的问题,索引

7.1)建立索引

rs1:PRIMARY> use mocker
switched to db mocker
rs1:PRIMARY> db.MockerTemplate.ensureIndex({mdmId:1, timestamp:1},{backgroud:true})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 2,
        "note" : "all indexes already exist",
        "ok" : 1
}
rs1:PRIMARY>

7.2)查看索引

rs1:PRIMARY> db.MockerTemplate.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "mocker.MockerTemplate"
        },
        {
                "v" : 1,
                "key" : {
                        "mdmId" : 1,
                        "timestamp" : 1
                },
                "name" : "mdmId_1_timestamp_1",
                "ns" : "mocker.MockerTemplate",
                "backgroud" : true
        }
]
rs1:PRIMARY>

 7.3)mongo备份

#!/bin/bash

#variable
LOG='mongoback_monitor.log'
LOG_TIME=$(date +%F-%H)
BACKUP_PATH='/data1/mongo_backup'
#PORT=(8082 27017)
cornsun_list='iotansible0001:8082,api-gateway0001:8082,api-gateway0002:8082'
mongo_hub='mongodb-hub-service0001:27017,mongodb-hub-service0002:27017'
mongo_vd='mongodb-vd0001:27017,mongodb-vd0002:27017'
#HOST=$(hostname)
#hubvd_list=(
#    mongodb-hub-service0001:27017,mongodb-hub-service0002:27017
#    mongodb-vd0001:27017,mongodb-vd0002:27017
#)

#cornsun_mongo path
MONGO_PATH=(
    /usr/local/bin/monitor/mongodb-linux-x86_64-rhel62-3.2.0/bin
    /home/envuser/monitor/mongodb-linux-x86_64-rhel62-3.2.0/bin
)


start(){
    echo "[${LOG_TIME}]=====cornsun backup start ========" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
    for path in "${MONGO_PATH[@]}"
    do
        if [ -d "$path" ]
        then
            if "${path}"/mongodump --host "${cornsun_list}" --db cronsun --excludeCollection job_log --excludeCollection log_scan --gzip --archive=${BACKUP_PATH}/cornsun-"${LOG_TIME}".gz &>> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
            then
                echo "cornsun ${cornsun_list} Backup successful, delete old files 3 days ago" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
                find $BACKUP_PATH -type f -mtime +3 -name "cornsun*.gz" -exec rm -f {} \;
                find $BACKUP_PATH -type f -mtime +3 -name "*.log" -exec rm -f {} \; 
            else
                echo "====cornsun ${cornsun_list} Backup failed!====" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
            fi
        else
            echo "=====dir $path is not exist.=====" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
        fi
    done
}

hubstart(){
    echo "[${LOG_TIME}]=====hub-vd backup start ========" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
    for dir in "${MONGO_PATH[@]}"
    do
        if [ -d "${dir}" ]
        then
            if "${dir}"/mongodump --host "${mongo_hub}"  --gzip --archive=${BACKUP_PATH}/"${mongo_hub:0:12}"-"${LOG_TIME}".gz &>> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
            then
                echo "${mongo_hub} Backup successful, delete old files 3 days ago" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
                find $BACKUP_PATH -type f -mtime +3 -name "*.gz" -exec rm -f {} \;
                find $BACKUP_PATH -type f -mtime +3 -name "*.log" -exec rm -f {} \;
            else
                echo "====Backup failed, hostname: ${mongo_hub} " >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
            fi 
 
        else
            echo "=====dir $dir is not exist.=====" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
        fi
    done
}

vdstart(){
    echo "[${LOG_TIME}]=====hub-vd backup start ========" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
    for dir in "${MONGO_PATH[@]}"
    do
        if [ -d "${dir}" ]
        then
            if "${dir}"/mongodump --host "${mongo_vd}"  --gzip --archive=${BACKUP_PATH}/"${mongo_vd:0:12}"-"${LOG_TIME}".gz &>> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
            then
                echo "${mongo_vd} Backup successful, delete old files 3 days ago" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
                find $BACKUP_PATH -type f -mtime +3 -name "*.gz" -exec rm -f {} \;
                find $BACKUP_PATH -type f -mtime +3 -name "*.log" -exec rm -f {} \;
            else
                echo "====Backup failed, hostname: ${mongo_vd} " >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
            fi 
 
        else
            echo "=====dir $dir is not exist.=====" >> ${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
        fi
    done
}


main(){
    if [ -d "${BACKUP_PATH}" ]
    then
        start
    else
        mkdir $BACKUP_PATH &>>${BACKUP_PATH}/"$(date +%Y%m%d)"-${LOG}
        start
    fi
}
main

7.4)mongo的恢复

/usr/local/mongodb/bin/mongorestore --gzip --archive=cornsun-2019-07-18-13.gz

 7.5) 手动备份

备份指定库(已测试)
mongodump --port 27017 --username root --password 123456 --authenticationDatabase admin -d cmdb_data

导出特定集合的数据
mongodump --db mydatabase --collection mycollection

导出满足特定查询条件的数据
mongodump --db mydatabase --collection mycollection --query '{ "field": "value" }'

使用gzip压缩导出备份数据
mongodump --db mydatabase --gzip --out /path/to/backup