zoukankan      html  css  js  c++  java
  • MongoDB

    一、初识MongoDB

      MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

      MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

      简单说,MongoDB和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等等。关系型数据库中有一个 "表" 的概念, "字段" 的概念, "数据条目" 的概念,MongoDB中也同样有以上的概念,,但是名称发生了一些变化,严格意义上来说,两者的概念即为相似,但又有些出入,不过无所谓,我们就当是以上概念就好啦。

      用如下示例进一步说明:

      这是我们用关系型数据库做的一张很简单的user表:

      id   name    age     gender
      1    刘涛     36      female
      2    孙红雷   40       male
      3    马伊利   35      female

      在MongoDB的数据结构如下:

      user = [
        {
          "id": 1,
          "name": "刘涛",
          "age": 36,
          "gender": female
        },
        {
          "id": 2,
          "name": "孙红雷",
          "age": 40,
          "gender": male
        },
        {
          "id": 3,
          "name": "马伊利",
          "age": 35,
          "gender": female
        }
      ]

      看到这里,你发现这不就是一个列表,里面放着三个字典吗?你说的对,如果你理解成了列表和字典,那么证明了你只会Python,在其他语言中它又是别的类型了,我们把这种类型叫做Json。

      那么你应该恍然大悟了吧,MongoDB的每个表(Collection)中存储的每条数据(Documents)都是一个一个的Json,Json中的每一个字段(Key)我们称之为Field,就此我们引出了三个关键字:Collection也就是关系型数据库中"表"的概念,Documents就是"数据条目",Field就是"字段"。

      接下来在你的电脑上安装MongoDB,本文以3.4版本为例,安装过程一路下一步即可,完成后找到安装目录下的bin目录,将其加入环境变量。

      注意:安装完成后打开终端,输入mongod,会显示如下错误信息:

      我们可以手动在上述提示目录,即c盘创建datadb目录,若不想放在c盘,也可以在其他磁盘,如d盘创建,如下:

      此时就可以成功开启mongodb服务了,且要指定mongodb的数据存放目录,如下:

      开启服务端后再打开一个终端开启mongo的客户端,如下:

      接下来就可以进行mongodb的操作了,如下图:

      注意:由上图我们发现,mongodb中使用了不存在的对象,就代表创建对象,接下来我们使用这以结论创建一张表(collection),如下图:

    二、MongoDB的数据类型 

      ObjectID :Documents 自生成的 _id;
      String: 字符串,必须是utf-8;
      Boolean:布尔值,true 或者false (注意,这里首字母要小写);
      Integer:整数 (Int32、Int64,就知道有个Int就行了,一般我们用Int32);
      Double:浮点数 (没有float类型,所有小数都是Double);
      Arrays:数组或者列表,多个值存储到一个键;
      Object:相当于Python中的字典;
      Null:空数据类型;
      Timestamp:时间戳;
      Date:存储当前日期或时间unix时间格式 (我们一般不用这个Date类型,时间戳可以秒杀一切时间类型);

      这里我们重点说一下ObjectID类型,它是MongoDB生成的类似关系型DB表主键的唯一key,具体由24个字节组成:

      1-8字节是时间戳;

      9-14字节的机器标识符,表示MongoDB实例所在机器的不同;

      15-18字节的进程id,表示相同机器的不同MongoDB进程;

      19-24字节是计数器;

      "_id" : ObjectId("5c3ee043949505956bbf9b33")
      
    #"5c3ee043" 代指的是时间戳,这条数据的产生时间;   #"949505" 代指某台机器的机器码,存储这条数据时的机器编号;   #"956b" 代指进程ID,多进程存储数据的时候,非常有用的;   #"bf9b33" 代指计数器,这里要注意的是,计数器的数字可能会出现重复,不是唯一的;   # 以上四种标识符拼凑成世界上唯一的ObjectID   # 只要是支持MongoDB的语言,都会有一个或多个方法,对ObjectID进行转换   # 注意:这个类型是不可以被JSON序列化的

    三、MongoDB的增删改查

    1、插入数据(insertinsert_oneinsert_many

      insert():插入一条或者多条数据,需要带有允许插入多条的参数,这个方法目前官方已经不推荐了

      insertOne({}):插入一条数据,官方推荐

      insertMany([{}]):插入多条数据,无需参数控制,官方推荐

    2、查询数据(findfindOne

      find():无条件查找,将该表(Collection)中所有的数据一次性返回

      findOne():无条件查找一条数据,默认当前Collection中的第一条数据

      find({条件},{排除字段}),示例如下:

     

    3、修改数据(updateupdateOneupdateMany

      语法:update/updateOne/updateMany({"条件"},{"关键字":{"修改内容"}})

      解释:根据条件修改内容,其中如果条件为空,那么将会修改Collection中所有的数据

      示例:

      update({"name":"tom"},{$set:{"age":43}}):表示将表中name等于tom的记录(documents)的age字段(field)改为21,与insert一样,官方已经不推荐

      updateOne({"age":43},{$set:{"age":25}}):将表中age等于43的记录(documents)的age字段(field)改为25,如出现多条符合条件的记录,只修改最靠前的数据,3.2版本之后有的,官方推荐

      updateMany({"age":25},{$set:{"age":22}}):将表中age等于25的记录(documents)的age字段(field)改为22,如出现多条符合条件的记录,修改所有符合条件的数据,3.2版本之后有的,官方推荐

    4、删除数据(removedeleteOnedeleteMany

      remove:删除满足条件的数据或者删除全部数据,官方已经不推荐了

      deleteOne:删除符合条件的一条数据,若有多条符合条件,默认删除符合条件的第一条,3.2版本之后有的,官方推荐写法

      deleteMany:删除符合条件的所有数据,若有多条符合条件,则删除符合条件的所有数据,3.2版本之后有的,官方推荐写法 

    5、查询中的数学比较符关键字( $lt、$gt、$lte、$gte$eq)

      $ltMongoDB中的"<",用"$lt",比如: "age":{$lt:22} 就是得到"age"小于22的数据

      $gt:MongoDB中的">",用"$gt",比如: "age":{$gt:22} 就是得到"age"大于22的数据

      $lteMongoDB中的"<=",用"$lte",比如: "age":{$lte:22} 就是得到"age"小于等于22的数据

      $gteMongoDB中的">=",用"$gte",比如: "age":{$gte:22} 就是得到"age"大于等于22的数据

      $eq:我们在之前的查询中遇到什么字段等于什么值时,使用冒号":"来表示,比如"name":"tom",除此之外,MongoDB中的"=",还可以用关键字"$eq"表示,比如:"age":{$eq:22} 就是得到"age"等于22的数据,但通常用冒号":"表示即可,不能用冒号的可用关键字"$eq"

    6、查询条件并列关系、或( $or )关系、子集( $in )关系、完全符合( $all )关系
      1)find({"name":"张三","age":15})

      2)find({$or:[{"name":"tom"},{"age":15}]})

      3)find({"age":{$in:[10,20,30,40]}}) 或者 find({"score":{$in:[55,77,80,91]}})

      4)find({"score":{$all:[58,88,77,95]}})

    7、MongoDB中的那些update修改器($inc、$set、$unset、$push、$pull$pushAll$pop) 

      在之前的update中,我们用过$set对数据进行修改,其实在update中还存在很多的$关键字,我们把update中的这些关键字叫做修改器,修改器很多,下面结合示例介绍几个:

      1)$inc:将查询到的结果,加上某一个值,然后保存

      2$set:暴力修改,我们在mongodb的基本操作中已经使用过该修改器

      3$unset:用来暴力删除字段(field

      4$push:用来对Array数据类型进行 增加 新元素的,相当于Pythonlist.append() 方法

      5$pull:用来对Array数据类型进行 删除 元素的,相当于Pythonlist.remove() 方法

      6$pushAll:用来对Array数据类型进行 迭代追加 ,相当于Pythonlist.extend() 方法

      7$pop:指定删除Array中的第一个 或 最后一个 元素

    8、"$"符的奇妙用法
      在
    MongoDB中有一个非常神奇的符号 "$","$"在update中加上关键字就变成了修改器,其实"$"字符独立出现也是有意义的,它代表符合条件的元素下标

      有如下collections:

      现需要把tom的score_list列表中的59改为60,操作如下:

      那么问题来了,若score_list中元素很多,且不知道要修改的元素索引,只知道修改前的值和修改后的值,此时改如何做呢?没错,就是使用"$",如下:

      注意:$中只能存储一个值,且是符合条件的第一个值。

    9、MongoDB的Array、Object的特殊操作

      相比关系型数据库,Array和Object是MongoDB比较特殊的类型了,特殊在哪里呢?在他们的操作上又有什么需要注意的呢?

      我们先建立一条数据(documents),包含 Array 和 Object 类型:

      {
        "_id" : ObjectId("5c406c65456ef1f8f2b06401"),
        "name" : "tom",
        "score" : [
            98,
            95,
            90,
            88
        ],
        "girlfriend" : {
            "name" : "alex",
            "gender" : "female",
            "age" : 30
        }
      }

      

      1)示例一:将score列表中的90改为80

     

      2)示例二:将tom的小于85的分数加上2分

      3)示例三:$只能存储一个值

      4)示例四:将girlfriend的age改为22

      5)示例五:若tom的girlfriend的age小于25时,给其值加2

      6)示例六:Array中嵌套Object的操作

        我们再建立如下数据演示:

      {
          "_id" : ObjectId("5c407d5e456ef1f8f2b06402"),
          "name" : "tom",
          "chengji" : [
              {
                  "title" : "python",
                  "desc" : "very good",
                  "score" : 90
              },
              {
                  "title" : "linux",
                  "desc" : "bad",
                  "score" : 60
              },
           {
                  "title" : "java",
                  "desc" : "good",
                  "score" : 82
           }
          ]
      }
      db.userinfo.update({"chengji.score":{$lt:70}},{$inc:{"chengji.$.score":2}})

      {"chengji.score":{$lt:70}},虽然chengjiArray,表示从内部的Object中找到score小于70的结果

      {$inc:{"chengji.$.score":2}}chengji中第$(小于70的第一个)Objectscore2

    10、Limit、Skip、Sort
      1)Limit 选取 : 从 Documents 中取出多少个

      2)Skip 跳过 : 跳过多少个Documents

      3)Sort 排序 : 将结果按照关键字排序(1 为升序 , -1 为降序) 

      4)Limit + Skip + Sort 混合使用

      注意:Sort + Skip + Limit 是有执行优先级的,他们的界别分别是,优先 Sort 其次 Skip 最后 Limt。

    四、pymongo

      类似pymysql,pymongo是python中操作mongodb数据库的模块。

    1、安装

    pip3 install pymongo

    2、使用pymongo

      1)增加

      import pymongo
    
      mongoclient = pymongo.MongoClient(host="127.0.0.1", port=27017)
      MongoDB = mongoclient["db1"]   # db1是mongodb中的一个数据库
    
      res = MongoDB.userinfo.insert_one({"name":"wusir", "age":32})
    
      print(res)  
      # <pymongo.results.InsertOneResult object at 0x0000019DEA5B6FC8>
      print(type(res))  # <class 'pymongo.results.InsertOneResult'>
      print(res.inserted_id) # 5c3eee24cf0e440838f79d3a
      print(type(res.inserted_id)) # <class 'bson.objectid.ObjectId'>
    
      res = MongoDB.userinfo.insert_many([
          {"name":"张三", "age":30},
          {"name":"李四", "age":18}
      ])
    
      print(res)  
      # <pymongo.results.InsertManyResult object at 0x000001DE80351088>
      print(type(res))  # <class 'pymongo.results.InsertManyResult'>
      print(res.inserted_ids) # [ObjectId('5c3eef71cf0e440ba4f5c40d'), ObjectId('5c3eef71cf0e440ba4f5c40e')]

      总结:

        - insert_one()插入数据一条数据(documents),返回值的inserted_id表示插入数据的"_id"值,ObjectID类型;

        - insert_many([])插入多条数据documents),返回值的inserted_ids表示插入数据的"_id"值组成的列表,列表中的元素也是ObjectID类型;

      2)查询

      import pymongo
    
      mongoclient = pymongo.MongoClient(host="127.0.0.1", port=27017)
      MongoDB = mongoclient["db1"]   # db1是mongodb中的一个数据库
      
      res = MongoDB.userinfo.find_one()  # 查询一条数据,返回字典
      print(res)
      # {'_id': ObjectId('5c3ee043949505956bbf9b33'), 'name': 'tom', 'age': 12.0}
    
      res = MongoDB.userinfo.find()  # 查询所有数据,返回cursor对象,可迭代
      print(res)
      # <pymongo.cursor.Cursor object at 0x0000016CF07D7358>
      print(list(res))
      # [{'_id': ObjectId('5c3ee043949505956bbf9b33'), 'name': 'tom', 'age': 12.0}, 
      # {'_id': ObjectId('5c3eed9dcf0e440980eb4e45'), 'name': 'alex', 'age': 38}, 
      # {'_id': ObjectId('5c3eee24cf0e440838f79d3a'), 'name': 'wusir', 'age': 32}, 
      # {'_id': ObjectId('5c3eef71cf0e440ba4f5c40d'), 'name': '张三', 'age': 30}, 
      # {'_id': ObjectId('5c3eef71cf0e440ba4f5c40e'), 'name': '李四', 'age': 18}]

      注意:同mongodb一样,pymongo也可以find({条件},{排除字段})或者find_one({条件},{排除字段})

      3)修改

      import pymongo
    
      mongoclient = pymongo.MongoClient(host="127.0.0.1", port=27017)
      MongoDB = mongoclient["db1"]   # db1是mongodb中的一个数据库
    
      res = MongoDB.userinfo.update_one({"name":"tom"},{"$set":{"age":15}})
    
      print(res)
      # <pymongo.results.UpdateResult object at 0x000001A888325E08>
      print(dir(res))
      # [..., '__delattr__',..., 'raw_result', 'upserted_id']
    
      res = MongoDB.userinfo.update_many({"age":15},{"$set":{"age":22}})
      print(res.raw_result)  # 修改结果,包括影响行数,是否存在需要修改的数据等
      # {'n': 2, 'nModified': 2, 'ok': 1.0, 'updatedExisting': True}

      总结:除上例中的$set之外,$push、$pull等方法都可以使用。

      4)删除

      import pymongo
    
      mongoclient = pymongo.MongoClient(host="127.0.0.1", port=27017)
      MongoDB = mongoclient["db1"]   # db1是mongodb中的一个数据库
    
      res = MongoDB.userinfo.delete_one({"name":"wusir"})
      res = MongoDB.userinfo.delete_many({"age":22})

      5)sort、limit、skip

      import pymongo
    
      mongoclient = pymongo.MongoClient(host="127.0.0.1", port=27017)
      MongoDB = mongoclient["db1"]   # db1是mongodb中的一个数据库
    
      res = MongoDB.userinfo.find().skip(2).limit(2)  # 跳过两条,显示两条
      print(list(res))
    
      # pymongo.ASCENDING表示升序,pymongo.DESCENDING表示降序
      res = MongoDB.userinfo.find().sort("age", pymongo.ASCENDING)
      print(list(res))
      res = MongoDB.userinfo.find().sort("age", pymongo.DESCENDING)
      print(list(res))

      6)字符串类型与ObjectID类型的相互转换

        我们知道ObjectID不能被序列化,而mongodb中的"_id"是ObjectID类型数据,且经常需要将数据json序列化后进行传输,下面介绍字符串类型与ObjectID类型相互转换。

      import pymongo
      from bson import ObjectId
    
      mongoclient = pymongo.MongoClient(host="127.0.0.1", port=27017)
      MongoDB = mongoclient["db1"]   # db1是mongodb中的一个数据库
    
      res = MongoDB.userinfo.find_one()
      s = res.get("_id")
      print(s)  # 5c3eef71cf0e440ba4f5c40d
      print(type(s))  # <class 'bson.objectid.ObjectId'>
      print(str(s))  # 5c3eef71cf0e440ba4f5c40d
      print(type(str(s)))  # <class 'str'>
    
      s = ObjectId("5c3eef71cf0e440ba4f5c40d")      # 强转成ObjectID类型
      res = MongoDB.userinfo.find_one({"_id":s})
      print(res)
      # {'_id': ObjectId('5c3eef71cf0e440ba4f5c40d'), 'name': '张三', 'age': 30}

     

  • 相关阅读:
    同异步调用、shutdown参数
    python学习笔记
    《深入浅出WPF》学习笔记之绘图和动画
    《深入浅出WPF》学习笔记之深入浅出话命令
    《深入浅出WPF》学习笔记之深入浅出话事件
    《深入浅出WPF》学习笔记之深入浅出话属性
    《深入浅出WPF》学习笔记之深入浅出话Binding
    《深入浅出WPF》学习笔记之控件与布局
    《深入浅出WPF》学习笔记之x名称空间详解
    《深入浅出WPF》学习笔记之系统学习XAML语法
  • 原文地址:https://www.cnblogs.com/li-li/p/10276355.html
Copyright © 2011-2022 走看看