zoukankan      html  css  js  c++  java
  • MongoDB

    MongoDB - 增删改查及聚合操作

    一. 数据库操作(database)

            Mysql       MongoDB
    数据表      table       Collections
    数据行      row         Documents
    数据列      字段        Field
    

    1. 创建及查看库

    1. 有则使用这个数据库没有则创建
    
    	use DATABASE_NAME
    
    2. 查看当前选择的数据库, 默认是test
    
    	db
    
    3. 查看数据库,默认有admin、local和"test",如果数据库生成但是没有集合(下面会讲)所以此时只有逻辑数据库产生并没有真正意义上的物理数据,这样看不到查询结果
    
    	show dbs
    

    2. 删除库

    use database_name #先切换到要删的库下
    
    db.dropDatabase() #删除当前库
    

    二. 集合collectionc=操作(相当于SQL数据库中的表table)

    1、增

    use db1#选择所在数据库
    #方式一:
    db.table1.insert({'a':1})#当第一个文档插入时,集合就会被创建并包含该文档
    #方式二:
    db.table2#创建一个空集合
    

    2、查

    show collections
    show tables#两者等价
    

    3、删

    db.table1.drop()
    
    #集合没有改的操作
    

    三. 文件操作

    1.增(insert)

    user0={
        "_id":1,
        "name":"alex",
        "age":10,
        'hobbies':['music','read','dancing'],
        'addr':{
            'country':'China',
            'city':'weifang'
        }
    }
    
    user1={
        "_id":2,
        "name":"wupeiqi",
        "age":20,
        'hobbies':['music','read','run'],
        'addr':{
            'country':'China',
            'city':'hebei'
        }
    }
    
    db.table1.insert(user0)	# 增加一个
    
    db.table1.insertMany([user0, user1])	# 增加多个
    

    2.删(delect,remove)

    #1、删除符合条件的第一个文档
    db.user.deleteOne({ 'age': 8 })#第一个包含有 'age': 8的文档
    
    #2、删除符合条件的全部
    db.user.deleteMany( {'addr.country': 'China'} ) #只要有内嵌文档,且内容含有country': 'China'的全都删除
    db.user.deleteMany({"_id":{"$gte":3}})#删除id大于等于3的所有
    
    #3、删除全部
    db.user.deleteMany({}) #等于是清空该集合(表)
    

    3.改(update)

    1.简单修改

    db.user.update({}, {$set:{}})	# 默认修改第一条
    
    db.user.updateOne({age:99}, {$set:{"name":"JW8"}})	# 默认修改第一条, 官方推荐.
    
    db.user.updateMany({age:99}, {$set:{"name":"JW8"}})	# 更新所有符合条件的数据
    

    2.加减操作: $inc

    #增加和减少$inc
    #年龄都+1
    db.user.update(
        {},
        {"$inc":{"age":1}},
        {"multi":true}
    )
    #年龄都-10
    db.user.update(
        {},
        {"$inc":{"age":-10}},
        {"multi":true}
    )
    

    3.添加删除数组内元祖$push $pop $pull

    $push的功能是往现有数组内添加元素

    #1、为名字为武大郎的人添加一个爱好read
    db.user.update({"name":"武大郎"},{"$push":{"hobbies":"read"}})
    
    #2、为名字为武大郎的人一次添加多个爱好tea,dancing
    db.user.update({"name":"武大郎"},{"$push":{
        "hobbies":{"$each":["tea","dancing"]}
    }})
    

    $pop的功能是按照位置只能从头或从尾即两端删元素,类似于队列。1代表尾,-1代表头

    #1、{"$pop":{"key":1}} 从数组末尾删除一个元素
    
    db.user.update({"name":"武大郎"},{"$pop":{
        "hobbies":1}
    })
    
    #2、{"$pop":{"key":-1}} 从头部删除
    db.user.update({"name":"武大郎"},{"$pop":{
        "hobbies":-1}
    })
    

    $pull可以自定义条件删除

    db.user.update({'addr.country':"China"},{"$pull":{
        "hobbies":"read"}
    },
    {
        "multi":true
    }
    )
    

    4.避免重复添加 $addToSet

    即多个相同元素要求插入时只插入一条

    db.urls.insert({"_id":1,"urls":[]})
    
    db.urls.update(
         {"_id":1},
         {
        "$addToSet":{
            "urls":{
            "$each":[
                'http://www.baidu.com',
                'http://www.baidu.com',
                'http://www.xxxx.com'
                ]
                }
            }
        }
    )
    

    5.限制大小,排序

    #1、了解:限制大小"$slice",只留最后n个
    
    db.user.update({"_id":5},{
        "$push":{"hobbies":{
            "$each":["read",'music','dancing'],
            "$slice":-2
        }
        }
    })
    
    #2、了解:排序The $sort element value must be either 1 or -1"
    db.user.update({"_id":5},{
        "$push":{"hobbies":{
            "$each":["read",'music','dancing'],
            "$slice":-1,
            "$sort":-1
        }
        }
    })
    
    #注意:不能只将"$slice"或者"$sort"与"$push"配合使用,且必须使用"$each"
    

    4.查

    1.简单用法

    db.user.find({})	# 查询所有符合条件的数据
    db.th.findOne({})	# 查询符合条件的第一条数据	
    
    db.th.findOne({name:2})	# 查询name字段 == 2 的数据
    db.stu.find({name:"辉哥",age:99})	# 并列条件 name与age 同时满足的
    

    2.比较运算:=,!= ('$ne') ,> ('$gt') ,< ('$lt') ,>= ('$gte') ,<= ('$lte')

    =,!= ('$ne') ,> ('$gt') ,< ('$lt') ,>= ('$gte') ,<= ('$lte')
    #1、select * from db1.user where id = 3
    db.user.find({"_id":3})
    
    #2、select * from db1.user where id != 3
    db.user.find({"_id":{"$ne":3}})
    
    #3、select * from db1.user where id > 3
    db.user.find({"_id":{"$gt":3}})
    
    #4、select * from db1.user where age < 3
    db.user.find({"age":{"$lt":3}})
    
    #5、select * from db1.user where id >= 3
    db.user.find({"_id":{"$gte":3}})
    
    #6、select * from db1.user where id <= 3
    db.user.find({"_id":{"$lte":3}})
    

    3.逻辑运算:MongoDB中字典内用逗号分隔多个条件是and关系,或者直接用$and,$o,r$not(与或非)

    #逻辑运算:$and,$or,$not
    #1 select * from db1.user where id >=3 and id <=4;
    db.user.find({"_id":{"$gte":3,"$lte":4}})
    
    #2 select * from db1.user where id >=3 and id <=4 and age >=40;
    db.user.find({
        "_id":{"$gte":3,"$lte":4},
        "age":{"$gte":40}
    })
    
    db.user.find({"$and":[
    {"_id":{"$gte":3,"$lte":4}},
    {"age":{"$gte":40}}
    ]})
    
    
    #3 select * from db1.user where id >=0 and id <=1 or id >=4 or name = "yuanhao";
    db.user.find({"$or":[
    {"_id":{"$lte":1,"$gte":0}},
    {"_id":{"$gte":4}},
    {"name":"yuanhao"}
    ]})
    
    #4 select * from db1.user where id % 2 = 1;
    db.user.find({"_id":{"$mod":[2,1]}})
    
    
    db.user.find({
        "_id":{"$not":{"$mod":[2,1]}}
    })
    

    4.成员运算:成员运算无非in和not in,MongoDB中形式为$in , $nin

    #1、select * from db1.user where age in (20,30,31);
    db.user.find({"age":{"$in":[20,30,31]}})
    
    #2、select * from db1.user where name not in ('alex','yuanhao');
    db.user.find({"name":{"$nin":['Stefan','Damon']}})
    

    5.正则:正则定义在/ /内

    # MongoDB: /正则表达/i
    
    #1、select * from db1.user where name regexp '^j.*?(g|n)$';
    db.user.find({'name':/^j.*?(g|n)$/i})#匹配规则:j开头、g或n结尾,不区分大小写
    

    6.查看指定字段:0表示不显示1表示显示

    #1、select name,age from db1.user where id=3;
    db.user.find({'_id':3},{'_id':0,'name':1,'age':1})
    
    #2、select name,age from db1.user where name regexp "^jin.*?(g|n)$";
    db.user.find({
        "name":/^jin.*?(g|n)$/i
    },
    {
        "_id":0,
        "name":1,
        "age":1
    }
    )
    

    7.对数组的查询:

    #查询数组相关
    #查hobbies中有dancing的人
    db.user.find({
        "hobbies":"dancing"
    })
    #查看既有dancing爱好又有tea爱好的人
    db.user.find({
        "hobbies":{"$all":["dancing","tea"]}
    })
    #查看第2个爱好为dancing的人
    db.user.find({
        "hobbies.2":"dancing"
    })
    #查看所有人的第2个到第3个爱好
    db.user.find(
    {},
    {
        "_id":0,
        "name":0,
        "age":0,
        "addr":0,
        "hobbies":{"$slice":[1,2]},
    }
    )
    
    #查看所有人最后两个爱好,第一个{}表示查询条件为所有,第二个是显示条件
    db.user.find(
    {},
    {
        "_id":0,
        "name":0,
        "age":0,
        "addr":0,
        "hobbies":{"$slice":-2},
    }
    )
    
    #查询子文档有"country":"China"的人
    db.user.find(
    {
        "addr.country":"China"
    }
    )
    

    8.对查询结果进行排序:sort() 1代表升序、-1代表降序

    db.user.find().sort({"name":1,})
    db.user.find().sort({"age":-1,'_id':1})
    

    9.分页:limit表示取多少个document,skip代表跳过几个document

    #这样就做到了分页的效果
    db.user.find().limit(2).skip(0)#前两个
    db.user.find().limit(2).skip(2)#第三个和第四个
    db.user.find().limit(2).skip(4)#第五个和第六个
    

    10.获取数量:count()

    #查询年龄大于30的人数
    #方式一:
    db.user.count({'age':{"$gt":30}}) 
    
    #方式二:
    db.user.find({'age':{"$gt":30}}).count()
    

    11.其他

    #1、查找所有
    db.user.find() #等同于db.user.find({})
    db.user.find().pretty()
    #2、去重
    db.user.find().distinct()
    
    #3、{'key':null} 匹配key的值为null或者没有这个key
    db.t2.insert({'a':10,'b':111})
    db.t2.insert({'a':20})
    db.t2.insert({'b':null})
    db.t2.find({"b":null})#得到的是b这个key的值为null和没有b这个key的文档
    { "_id" : ObjectId("5a5cc2a7c1b4645aad959e5a"), "a" : 20 }
    { "_id" : ObjectId("5a5cc2a8c1b4645aad959e5b"), "b" : null }
    

    四. 聚合操作

    我们在查询时肯定会用到聚合,在MongoDB中聚合为aggregate,聚合函数主要用到$match $group $avg $project $concat

    设我们的数据库中有这样的数据

    from pymongo import MongoClient
    import datetime
    
    client=MongoClient('mongodb://root:123@localhost:27017')
    table=client['db1']['emp']
    # table.drop()
    
    l=[
    ('武大郎','male',18,'20170301','烧饼检察官',7300.33,401,1), 
    ('武松','male',78,'20150302','公务员',1000000.31,401,1),
    ('宋江','male',81,'20130305','公务员',8300,401,1),
    ('林冲','male',73,'20140701','公务员',3500,401,1),
    ('柴进','male',28,'20121101','公务员',2100,401,1),
    ('卢俊义','female',18,'20110211','公务员',9000,401,1),
    ('高俅','male',18,'19000301','公务员',30000,401,1),
    ('鲁智深','male',48,'20101111','公务员',10000,401,1),
    
    ('史进','female',48,'20150311','打手',3000.13,402,2),
    ('李逵','female',38,'20101101','打手',2000.35,402,2),
    ('周通','female',18,'20110312','打手',1000.37,402,2),
    ('石秀','female',18,'20160513','打手',3000.29,402,2),
    ('李忠','female',28,'20170127','打手',4000.33,402,2),
    
    ('吴用','male',28,'20160311','文人',10000.13,403,3), 
    ('萧让','male',18,'19970312','文人',20000,403,3),
    ('安道全','female',18,'20130311','文人',19000,403,3),
    ('公孙胜','male',18,'20150411','文人',18000,403,3),
    ('朱贵','female',18,'20140512','文人',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)
    

    $match和 $group:相当于sql语句中的where和group by

    {"$match":{"字段":"条件"}},可以使用任何常用查询操作符$gt,$lt,$in等
    
    #例1、select * from db1.emp where post='公务员';
    db.emp.aggregate({"$match":{"post":"公务员"}})
    
    #例2、select * from db1.emp where id > 3 group by post;  
    db.emp.aggregate(
        {"$match":{"_id":{"$gt":3}}},
        {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}}
    )
    
    #例3、select * from db1.emp where id > 3 group by post having avg(salary) > 10000;  
    db.emp.aggregate(
        {"$match":{"_id":{"$gt":3}}},
        {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}},
        {"$match":{"avg_salary":{"$gt":10000}}}
    )
    

    $group具体

    {"$group":{"_id":分组字段,"新的字段名":聚合操作符}}
    
    #1、将分组字段传给$group函数的_id字段即可
    {"$group":{"_id":"$sex"}} #按照性别分组
    {"$group":{"_id":"$post"}} #按照职位分组
    {"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多个字段分组,比如按照州市分组
    
    #2、分组后聚合得结果,类似于sql中聚合函数的聚合操作符:$sum、$avg、$max、$min、$first、$last
    #例1:select post,max(salary) from db1.emp group by post; 
    db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}})
    
    #例2:取每个部门最大薪资与最低薪资
    db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})
    
    #例3:如果字段是排序后的,那么$first,$last会很有用,比用$max和$min效率高
    db.emp.aggregate({"$group":{"_id":"$post","first_id":{"$first":"$_id"}}})
    
    #例4:求每个部门的总工资
    db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":"$salary"}}})
    
    #例5:求每个部门的人数
    db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})
    
    #3、数组操作符
    {"$addToSet":expr}#不重复
    {"$push":expr}#重复
    
    #例:查询岗位名以及各岗位内的员工姓名:select post,group_concat(name) from db1.emp group by post;
    db.emp.aggregate({"$group":{"_id":"$post","names":{"$push":"$name"}}})
    db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"}}})
    

    $project:用于投射,即设定该键值对是否保留。1为保留,0为不保留,可对原有键值对做操作后增加自定义表达式

    {"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表达式"}}
    
    #select name,post,(age+1) as new_age from db1.emp;
    db.emp.aggregate(
        {"$project":{
            "name":1,
            "post":1,
            "new_age":{"$add":["$age",1]}
            }
    })
    

    更多自定义表达式

    #1、表达式之数学表达式
    {"$add":[expr1,expr2,...,exprN]} #相加
    {"$subtract":[expr1,expr2]} #第一个减第二个
    {"$multiply":[expr1,expr2,...,exprN]} #相乘
    {"$divide":[expr1,expr2]} #第一个表达式除以第二个表达式的商作为结果
    {"$mod":[expr1,expr2]} #第一个表达式除以第二个表达式得到的余数作为结果
    
    #2、表达式之日期表达式:$year,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second
    #例如:select name,date_format("%Y") as hire_year from db1.emp
    db.emp.aggregate(
        {"$project":{"name":1,"hire_year":{"$year":"$hire_date"}}}
    )
    
    #例如查看每个员工的工作多长时间
    db.emp.aggregate(
        {"$project":{"name":1,"hire_period":{
            "$subtract":[
                {"$year":new Date()},
                {"$year":"$hire_date"}
            ]
        }}}
    )
    
    
    #3、字符串表达式
    {"$substr":[字符串/$值为字符串的字段名,起始位置,截取几个字节]}
    {"$concat":[expr1,expr2,...,exprN]} #指定的表达式或字符串连接在一起返回,只支持字符串拼接
    {"$toLower":expr}
    {"$toUpper":expr}
    
    db.emp.aggregate( {"$project":{"NAME":{"$toUpper":"$name"}}})
    
    #4、逻辑表达式
    $and
    $or
    $not
    

    排序:$sort、限制:$limit、跳过:$skip

    {"$sort":{"字段名":1,"字段名":-1}} #1升序,-1降序
    {"$limit":n} 
    {"$skip":n} #跳过多少个文档
    
    #例1、取平均工资最高的前两个部门
    db.emp.aggregate(
    {
        "$group":{"_id":"$post","平均工资":{"$avg":"$salary"}}
    },
    {
        "$sort":{"平均工资":-1}
    },
    {
        "$limit":2
    }
    )
    #例2、
    db.emp.aggregate(
    {
        "$group":{"_id":"$post","平均工资":{"$avg":"$salary"}}
    },
    {
        "$sort":{"平均工资":-1}
    },
    {
        "$limit":2
    },
    {
        "$skip":1
    }
    )
    

    随机选取n个:$sample

    #集合users包含的文档如下
    { "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }
    { "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false  }
    { "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true  }
    { "_id" : 4, "name" : "li", "q1" : true, "q2" : false  }
    { "_id" : 5, "name" : "annT", "q1" : false, "q2" : true  }
    { "_id" : 6, "name" : "li", "q1" : true, "q2" : true  }
    { "_id" : 7, "name" : "ty", "q1" : false, "q2" : true  }
    
    #下述操作时从users集合中随机选取3个文档
    db.users.aggregate(
       [ { $sample: { size: 3 } } ]
    )
    

    练习题

    1. 查询岗位名以及各岗位内的员工姓名

    2. 查询岗位名以及各岗位内包含的员工个数

    3. 查询公司内男员工和女员工的个数

    4. 查询岗位名以及各岗位的平均薪资、最高薪资、最低薪资

    5. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资

    6. 查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数

    7. 查询各岗位平均薪资大于10000的岗位名、平均工资

    8. 查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资

    9. 查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序

    10. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资升序排列

    11. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列,取前1个

      1. 查询岗位名以及各岗位内的员工姓名
      db.emp.aggregate({"$group":{"_id":"$post","names":{"$push":"$name"}}})
      
      2. 查询岗位名以及各岗位内包含的员工个数
      db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})
      
      3. 查询公司内男员工和女员工的个数
      db.emp.aggregate({"$group":{"_id":"$sex","count":{"$sum":1}}})
      
      4. 查询岗位名以及各岗位的平均薪资、最高薪资、最低薪资
      db.emp.aggregate({"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"},"max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})
      
      5. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
      db.emp.aggregate({"$group":{"_id":"$sex","avg_salary":{"$avg":"$salary"}}})
      
      6. 查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数
      db.emp.aggregate(
      {
          "$group":{"_id":"$post","count":{"$sum":1},"names":{"$push":"$name"}}
      },
      {"$match":{"count":{"$lt":2}}},
      {"$project":{"_id":0,"names":1,"count":1}}
      )
      
      7. 查询各岗位平均薪资大于10000的岗位名、平均工资
      db.emp.aggregate(
      {
          "$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}
      },
      {"$match":{"avg_salary":{"$gt":10000}}},
      {"$project":{"_id":1,"avg_salary":1}}
      )
      
      8. 查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资
      db.emp.aggregate(
      {
          "$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}
      },
      {"$match":{"avg_salary":{"$gt":10000,"$lt":20000}}},
      {"$project":{"_id":1,"avg_salary":1}}
      )
      
      9. 查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序
      db.emp.aggregate(
      {"$sort":{"age":1,"hire_date":-1}}
      )
      
      10. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资升序排列
      db.emp.aggregate(
      {
          "$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}
      },
      {"$match":{"avg_salary":{"$gt":10000}}},
      {"$sort":{"avg_salary":1}}
      )
      
      11. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列,取前1个
      db.emp.aggregate(
      {
          "$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}
      },
      {"$match":{"avg_salary":{"$gt":10000}}},
      {"$sort":{"avg_salary":-1}},
      {"$limit":1},
      {"$project":{"date":new Date,"平均工资":"$avg_salary","_id":0}}
      )
  • 相关阅读:
    2、容器初探
    3、二叉树:先序,中序,后序循环遍历详解
    Hebbian Learning Rule
    论文笔记 Weakly-Supervised Spatial Context Networks
    在Caffe添加Python layer详细步骤
    论文笔记 Learning to Compare Image Patches via Convolutional Neural Networks
    Deconvolution 反卷积理解
    论文笔记 Feature Pyramid Networks for Object Detection
    Caffe2 初识
    论文笔记 Densely Connected Convolutional Networks
  • 原文地址:https://www.cnblogs.com/konghui/p/10603327.html
Copyright © 2011-2022 走看看