zoukankan      html  css  js  c++  java
  • mongoDB的基本用法

     

    一.MongoDB初识

    什么是MongoDB

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

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

    它和我们使用的关系型数据库最大的区别就是约束性,可以说文件数据库基本不存在约束性,理论上没有外键约束,没有存储数据类型约束等等

    关系型数据库中有一个"表"的概念,有"字段"的概念,有"数据条目"的概念

    MongoDB中也同样有以上的概念,但是名称发生了一些变化,严格意义上来说,两者的概念极为相似,但又有些出入.

    光说该是有些模糊,下面举一个小小的例子进行一些对比.

    我们来做一张表:

    这是我们用关系型数据库做的一张很简单的User表对吧

    接下来我们在看一下MongoDB的数据结构

    复制代码
    User = [{
        "name": "武大郎",
        "age": 18,
        "gender": "男"
    }, {
        "name": "孙悟空",
        "age": 100000,
        "gender": "男"
    }, {
        "name": "蔡文姬",
        "age": 16,
        "gender": "女"
    }]
    复制代码

    就不就是个列表,里面放着三个字典吗.它实际是一个json数据.

    那么你就该 恍然大悟了吧,MongoDB的每个表(collection)中存储的每条数据(documents)都是一个一个的json,json中的每一个字段(key)我们称之为:field

    就此我们引出了三个关键字,collection也就是关系型数据库中"表"的概念,document就是"数据条目",field就是字段

    这么说,可能还不太明白.看表:

    MySQL MongoDB
    DB DB
    Table colletions
    字段 field
    row documents

    MongoDB安装

    mongodb(主程序)
    链接:https://pan.baidu.com/s/139_BqPbh0IPcDMPmkWnS8w 密码:fybs

    你必须得先安装上数据库才能继续装X

    关于MongoDB的安装,真的没有难度,真的真的没有难度,来跟着DragonFire一步一步操作,带你Legendary

    首先分享给你一个MongoDB 3.4的msi安装包 点击这里可以下载哦(如果不能下载证明我还没搞定分享msi,自己下载一个吧)

    选择默认安装/选择安装

    选择 安装

    安装完成之后,开始进入配置环节,首先我们要进入目录:

    "C:Program FilesMongoDBServer3.4in"

    带着你配置环境变量,让X装的更加自然更加美:

    之后的操作,windows 7 与 windows 10 不太一样,大同小异啦

    windows 10 一路到底的"确定"

    windows 7 在这里需要注意的是,Path路径移动到最后,输入:"  ;C:Program FilesMongoDBServer3.4in  " 一定要带上 "  ;  " 哦

    因为没有找到windows 7 操作系统的计算机,所以这里只能给windows 7 的同学说声抱歉了

    OK!到了这里我们基本已经完成了部分操作了

    我们来试一下成果吧

    打开cmd窗口进行一次ZB的操作吧

    那我们来创建一个" C:datadb "的目录吧

    好了目录已经有了,再次ZB试一下

    好了开启成功了

    那么服务开启了,客户端怎么去连接呢,这时我们需要另一个cmd窗口开启mongo的客户端

    到此,我们成功的完成了,服务端的部署开启,还有客户端的链接,如果你还想继续往下学习的话,我给你一句金玉良言

    千万别把这两个cmd窗口关了,不然你还得重新打开一次,哈哈哈哈哈哈哈哈!!!!

    本文参考链接:

    https://www.cnblogs.com/DragonFire/p/9135630.html

     二增删改查操作

    MongoDB不存在SOL语句,操作它,需要使用ORM语法

    创建数据库

    这里和一般的关系型数据库一样,都要建立一个自己的数据库空间

    MongoDB设计比较随意,没有就认为你是在创建,use CRM是不存在的,所以MongoDB就认为你是要创建并使用,(这个概念很重要)

    MongoDB中如果你使用了不存在的对象,那么就等于你在创建这个对象

    然后我们使用这一说法来穿件一张表(collection)试试

    看来是成功创建了一个CRM的course表,那么接下来就是在表中添加数据了.

    插入数据

    insert(不推荐)

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

     db.course.insert({"name":"python","price":1080})

     效果如下:

    inserOne

    插入一条数据,官方推荐

    db.course.insertOne({"name":"linux","price":1070})

    效果如下

    我们可以看出来两种方法的返回值截然不同对吧

    insertMany

    插入多条数据,无需参数控制,官方推荐

    db.course.insertOne({"name":"linux","price":1070},{"name":"nodejs","price":1090})

     效果如下:

    这个就是向我们显示我们向CRM.course中插入了两条数据,他是将列表中的数据进行迭代添加.

     查询数据

    主要是(find findOne),这里没有findMany

    find

    这里不是select,如果你的第一反应是select证明你的关系型数据库没白学

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

    db.course.find()

     结果如下:

    条件查找:price等于1070的数据,这里会返回多条结果:

    db.course.find({"price":1070})

    结果如下:

    说到这里,有的同学不禁要问一下:"_id":ObjectId("乱七八糟一道对看着毫无关系的一对字符串") 是什么,我们插入的时候并没有一个字段(Field)并没有_id这个,

    对了这就是MongoDB自动给我们添加到系统唯一标识"_id" 是一个ObjectId 类型,我们会在数据类型中第一个说到他(MongoDB 之 数据类型 最无聊! But 最有用! MongoDB - 3)

     findOne

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

     db.course.findOne()

     结果如下:

    条件查找一条price等于1070的数据,如果有多条数据则返回更靠前的数据:

    db.course.findOne({"price":1070})

    结果如下:

    查询数据的时候,发现了有些数据出现错误了,要修改怎么办呢?

    修改数据

    主要用到,(update updataOne updateMany)之 跟insert一样,不推荐update的写法.

    update(不推荐)

    根据条件修改该条数据的内容

    db.course.update({"name":"python"},{$set:{"price":1080}})

    结果如下:

    把name等于python中的price改为1080,这里要注意的是({"条件"},{"关键字":{修改内容}}),其中如果条件为空,那么将会修改collection中所有的数据.

    关于$set关键字的解释就是,本节最后再说,留个悬念.

    updateOne(推荐)

    根据条件修改一条数据的内容,如果出现多条,只修改最靠前的一条数据

    举例;把price等于1070的所有数据的name更改为hello world

    db.course.updateOne({"price":1070},{$set:{"name":"hello world"}})

     结果如下:

    updateMany(推荐)

    根据条件修改所有数据的内容,多条修改

    举例:把price等于1070的所有数据中的name改为Go

    db.course.updateMany({"price":1070},{$set:{"name":"Go"}})

     结果如下:

    上述中有一个$set的悬念,这个悬念可能在往后一些

    但是$set:{"name":"Go"}还是需要了解一下:$set是update时的关键字,表示我要设置name属性的值为"Go"

    那么我们之前说过MongoDB的灵活性,没有就代表我要创建,所以说如果该条documents没有name属性,它就会自动创建一个,name属性,并且复制为"Go"

     更改了半天,这些数据我都不想要怎么办?

    删除数据

    MongoDB提供了三个用于删除的API,分别是:

    db.collection.remove()

    db.collection.deleteOne()

    db.collection.deleteMany()

    这三个API都不支持一个过滤条件参数,用于匹配到满足条件的document,然后进行删除操作.

    remove(不推荐)

    remove()方法已经过时了,现在官方推荐使用deleteOne() 和deleteMany()方法.

    remove({}):无条件删除数据,这里要注意了,这是删除所有数据,清空collection

    当然了,我现在还不会操作! 不然就不能再往下演示了,我得重新添加数据.

    remove还支持条件删除

    例句:删除name等于"python"的所有document

    db.course.remove({"name":"python"})

     结果如下:

    deleteOne(推荐)

    删除匹配到的所有的document中的第一个

    db.course.deleteOne({"price":1070})

     结果如下:

     

    deleteMany(推荐)

    删除所有匹配到的document

     db.course.deleteMany({"name":"Go"})

     结果如下

    这里我们发现所有name为Go的数据已经被删除了

    三.数据类型

    丰富多彩的数据类型世界

    首先我们要先了解一下MongoDB中有什么样的数据类型:

    objectID : Documents自生产成的_id

    String : 字符串,必须是utf-8

    Boolean : 布尔值,true或者false("这里有坑~ 在python中True False 首字母大写")

    Integer : 整数(Int32 Int64 你们就知道有个Int就行了,一般我们用Int32)

    Double : 浮点数(没有float类型,所有小数都是Double)

    Arrays : 数组或者列表,多个值存储到一个键(list,python中的list)

    Object : 如果你学过python的话,那么这个概念特别好理解,就是python中的字典,这个数据类型就是字典

    Null : 空数据类型,一个特殊的概念, "None   Null"

    Timestamp : 时间戳

    Date : 存储当前日期或者时间Unix时间格式(我们一般不用这个date类型,时间戳可以秒杀一切时间类型)

    剖析MongoDB的数据类型

    我们根据以上所说的数据类型(捡重点说)展开说明:

    Object ID

    > db.Oldboy.find()
    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Elizabeth", "age" : 20 }

    解释:

    复制代码
    "_id" : ObjectId("5b151f8536409809ab2e6b26")
    "5b151f85" 代指的是时间戳,这条数据的产生时间
    "3640998"  代指某台机器的机器码,存储这条数据的机器标号
    "09ab"        代指进程ID,多进程存储数据的时候,非常有用
    "2e6b26"   代指计数器,这里要注意的是,计数器的数字可能会出现重复,不是唯一的
    以上四种标识符拼凑成世界上唯一的ObjectId
    只要是支持MongoDB的语言,都会有一个或多个方法,对ObjectId进行转换
    可以得到以上四重信息
    
    注意:这个类型是不可以被json序列化的
    复制代码

     这是MongoDB生成的类似关系DB表主键的唯一key,具体由24个字节组成;

    0-8 字节是时间戳

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

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

    19-24 字节是计数器

     

    String

    > db.Oldboy.find()
    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Elizabeth", "age" : 20 }
    
    UTF-8字符串,记住是UTF-8字符串

     

     Integer

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Elizabeth", "age" : 20 }

    整数(Int32 Int64 你们就世道有一个Int就行了,一般我们用Int32)

    Double

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Apple", "Price" : 5.8 }

    浮点数(MongoDB中没有float类型,所有小数都是Double)

    Arrays

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Apple", "place" : ["China","America","New Zealand"] }

    数组或者列表,多个值存储到一个键 (list哦,大Python中的List哦

    Object

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "LuffyCity", "course" : {"name" : "Python","price" : 19800 } }

    如果你学过Python的话,那么这个概念特别好理解,就是Python中的字典,这个数据类型就是字典

    Null

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "atmosphere", "price" : null }

    空数据类型 , 一个特殊的概念,None Null

    Timestamp :时间戳

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Shanghai", "date" : 1528183743111 }

    Date

    { "_id" : ObjectId("5b151f8536409809ab2e6b26"), "name" : "Beijing", "date" : ISODate("2018-06-05T15:28:33.705+08:00") }

    存储当前日期或时间格式 (我们一般很少使用这个Date类型,因为时间戳可以秒杀一切时间类型)

    数据类型就介绍到这里了,接下来我们就要学习一下在数据进行增删改查时,数据类型的特殊用法

    本文参考链接:

    https://www.cnblogs.com/DragonFire/p/9135854.html

    四.$关键字及$修改器

    上面提到过$set这个系统关键字,用来修改值的

    但是MongoDB中类似这样的关键字有很多,$lt $gt $lte $gte 等等,这么多我们也不方便记,这里我们说几个比较常见的

    准备基础数据

    复制代码
    # 清空所有数据
    > db.course.remove({})
    WriteResult({ "nRemoved" : 0 })
    
    # 插入三条数据 > db.course.insertMany([{"name":"python","score":59},{"name":"linux","score":100},{"name":"Go","score":80}]) { "acknowledged" : true, "insertedIds" : [ ObjectId("5c3f10265591b5b80202c909"), ObjectId("5c3f10265591b5b80202c90a"), ObjectId("5c3f10265591b5b80202c90b") ] }
    # 查询所有数据 > db.course.find() { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59 } { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 } { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }
    复制代码

    常见的$关键字

      :    (等于)

    在MongoDB中什么字段等于什么值其实就是":"来搞定, 比如"name":"linux"

    > db.course.find({"name":"linux"})
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }

    $in

    查询一个键的多个值

    > db.course.find({"name":{$in:["linux","Go"]}})
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

    $or

    满足任意$or条件的数据,至少要满足一个

    > db.course.find({$or:[{"score":100},{"score":80}]})
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

    $ge(大于)

    在MongoDB中大于 >号我们用 :$gt 比如:"score":{$gt:80}就是得到"score"大于80的数据

    > db.course.find({"score":{$gt:70}})
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

    $lt (小于)

    小于: 在MongoDB中的小于 < 号我们用: "score":{$lt:80} 就是得到"score"小于80 的数据

    > db.course.find({"score":{$lt:80}})
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59 }

    $gte (大于等于)

    大于等于 : 在MongoDB中的 大于等于 >= 号 我们用 : $gte  比如 :  "score" : { $gte : 80 } 就是 得到 "score" 大于等于 80 的数据

    > db.course.find({"score":{$gte:80}})
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64b"), "name" : "Python", "score" : 100 }
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64c"), "name" : "Go", "score" : 80 }

    $lte(小于等于)

    小于等于 : 在MongoDB中的 小于等于 <= 号 我们用 : $lte  比如 :  "score" : { $lte : 80 } 就是 得到"score"小于等于80的数据

    > db.course.find({"score":{$lte:80}})
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64a"), "name" : "Linux", "score" : 59 }
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64c"), "name" : "Go", "score" : 80 }

    update修改器

    常用的update修改器: $inc $set $unset $push $pull

    在此之前的update中,我们用过$set,对数据进行过更新,其实在update中还存在很多的$关键字,我们把update中的这些关键字叫做修改器

    修改器很多,这里挑一些重要的来说

    $inc

    python中的  变量+=1 ,将查询到的结果,加上某一个值 然后保存

    还是上面的collection数据,我们来试一下$inc, 让不及格的python变成60分

    > db.course.updateOne({"score":59},{$inc:{"score":1}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find({"name":"python"})
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 60 }

    成功了,{$inc:{"score":1}}的意思是,"score"的原有数值上面 +1

    查看所有数据

    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 60 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

    我们再来实验一次,把60改为20,这怎么操作呢,其实可以理解为在 60 上加一个 -40

    > db.course.updateOne({"score":60},{$inc:{"score":-40}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

    又成功了 , {$inc:{"score":-20}}也来越喜欢英俊潇洒又不会翻车的自己了

    $inc 的用法是不是很简单啊,就是原有基础上在增加多少对吧

    查看所有数据

    > db.course.find()
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64a"), "name" : "Linux", "score" : 20 }
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64b"), "name" : "Python", "score" : 100 }
    { "_id" : ObjectId("5b98f5b3430c27444ccdd64c"), "name" : "Go", "score" : 80 }

     $set

    此前我们已经提到过$set的用法和特性(没有就自动添加一条)了

    在做一个例子:把score为100分的price复制为99.8

    > db.course.updateOne({"score":100},{$set:{"price":99.8}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 60 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100, "price" : 99.8 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

     发现linux多了一个price属性

    在把score为20分的score赋值为59分

    > db.course.updateOne({"score":20},{$set:{"score":59}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100, "price" : 99.8 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

    $unset

    用来删除key(field)的

    做一个例子,刚才我们有一个新的price这个field,现在我们来删除它

    > db.course.updateOne({"score":100},{$unset:{"price":1}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }

    成功了! {$unset:{"price" : 1}} 就是删除 "price" 这个 field 相当于 关系型数据库中删除了 字段

    $push

    它是用来对Array(list)数据类型进行增加 新元素的,相当于python中list.append()方法

    复制代码
    > db.course.update({},{$set:{"test_list":[1,2,3,4,5]}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59, "test_list" : [ 1, 2, 3, 4, 5 ] }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90c"), "name" : "linux", "price" : 1070 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90d"), "name" : "nodejs", "price" : 1090 }
    复制代码

    使用update $set的方法只能为document中的第一条添加

    使用updateMany $set 的方法 可以为所有满足条件的document添加, 注意我这里的条件为"{}",就算为"{}"也要写上

    接下来我们就要向队列中进行添加了:将"score" 为59的document中"test_list"添加一个6

    复制代码
    > db.course.update({"score":59},{$push:{"test_list":6}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59, "test_list" : [ 1, 2, 3, 4, 5, 6 ] }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90c"), "name" : "linux", "price" : 1070 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90d"), "name" : "nodejs", "price" : 1090 }
    复制代码

    $pop

    指定Array中的第一个或最后一个元素

    做一个小栗子:删除"score"等于59分 test_list的最后一个元素

    复制代码
    > db.course.updateMany({"score":59},{$pop:{"test_list":1}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59, "test_list" : [ 1, 2, 3, 4, 5 ] }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90c"), "name" : "linux", "price" : 1070 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90d"), "name" : "nodejs", "price" : 1090 }
    
    复制代码

     怎么删除第一个呢?

    复制代码
    > db.course.updateMany({"score":59},{$pop:{"test_list":-1}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5c3f10265591b5b80202c909"), "name" : "python", "score" : 59, "test_list" : [ 2, 3, 4, 5 ] }
    { "_id" : ObjectId("5c3f10265591b5b80202c90a"), "name" : "linux", "score" : 100 }
    { "_id" : ObjectId("5c3f10265591b5b80202c90b"), "name" : "Go", "score" : 80 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90c"), "name" : "linux", "price" : 1070 }
    { "_id" : ObjectId("5c3f1ac55591b5b80202c90d"), "name" : "nodejs", "price" : 1090 }
    复制代码

    {$pop:{"test_list" : -1}}  -1 代表最前面, 1 代表最后边 (这和我们大Python正好相反) 记住哦

    五.''$"的奇妙用法

    在MongoDB中有一个非常神奇的符号"$"

    "$"在update中 加上关键字,就变成了修改器

    其实 "$"字符 独立出现也是有意义的,我起名叫做代指符

    准备基础数据

     View Code

    首先看个例子:  现在把 "score": 100 的 test_list 里面的 2 改为 9

    > db.course.updateOne({"score":100},{$set:{"test_list.0":9}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5b990189430c27444ccdd650"), "name" : "Linux", "score" : 100, "test_list" : [ 9, 3, 4 ] }
    { "_id" : ObjectId("5b990189430c27444ccdd651"), "name" : "Python", "score" : 80, "test_list" : [ 1, 2, 3, 4, 5 ] }
    { "_id" : ObjectId("5b990189430c27444ccdd652"), "name" : "Go", "score" : 59, "test_list" : [ 1, 2, 3, 4, 5 ] }

    {$set :{"test_list.0" : 9}} 这样就是对应 Array 中的下标进行修改了 "test_list.下标"

    问题来了 如果 是 一个很长很长很长的 Array 你要查找其中一个值,把这个值修改一下怎么整呢?

    把9还原成2

    > db.course.updateMany({"score":100,"test_list":9},{$set:{"test_list.$":2}})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    > db.course.find()
    { "_id" : ObjectId("5b990189430c27444ccdd650"), "name" : "Linux", "score" : 100, "test_list" : [ 2, 3, 4 ] }
    { "_id" : ObjectId("5b990189430c27444ccdd651"), "name" : "Python", "score" : 80, "test_list" : [ 1, 2, 3, 4, 5 ] }
    { "_id" : ObjectId("5b990189430c27444ccdd652"), "name" : "Go", "score" : 59, "test_list" : [ 1, 2, 3, 4, 5 ] }

    神奇不神奇?

    $ 字符 在语句中代表了什么呢? 下标,位置

    解释一下: 首先我们查询一下db.course.findOne({"score":100,"test_list":3}) 返回 给我们满足条件的数据对吧

    复制代码
    > db.course.findOne({"score":100,"test_list":3})
    {
            "_id" : ObjectId("5b990189430c27444ccdd650"),
            "name" : "Linux",
            "score" : 100,
            "test_list" : [
                    2,
                    3,
                    4
            ]
    }
    复制代码

    那么 如果 我们 使用 update的话, 满足条件的数据下标位置就会传递到 $ 字符中,在我们更新操作的时候就相当于 对这个位置 的元素进行操作

    本文参考链接:

    https://www.cnblogs.com/DragonFire/p/9146896.html

    六.Array Object的特殊操作

    相比关系型数据库,Array[1,2,3,4,5]和Object{'name':'python'}是MongoDB比较特殊的类型了特殊在哪里呢?

    在他们的操作上又有深恶需要注意的呢?

    那我们现建立一条数据,包含Array和object类型

    复制代码
    # 清空所有数据
    > db.course.remove({})
    WriteResult({ "nRemoved" : 3 })
    
    # 插入一条数据
    > db.course.insert({"name":"路飞学城-骑士计划","price":[19800,19500,19000,18800],"other":{"start":"2018年8月1日","start_time":"08:30","count":150}})
    WriteResult({ "nInserted" : 1 })
    
    # 查看所有数据
    > db.course.find()
    { "_id" : ObjectId("5c3f2c065591b5b80202c911"), "name" : "路飞学城-骑士计划", "price" : [ 19800, 19500, 19000, 18800 ], "other" : { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 } }
    复制代码

     数据看着可能不太直观,大概是这个样子

    复制代码
    {
        "_id" : ObjectId("5b17d01a49bf137b585df891"),
        "name" : "路飞学城-骑士计划",
        "price" : [
            19800,
            19500,
            19000,
        ],
        "other" : {
            "start" : "2018年8月1日",
            "start_time" : "08:30",
            "count" : 150
        }
    }
    复制代码

    好的,这条数据已经完成了

    针对这条数据我们进行一系列的操作,并讲解使用方式

    Array 小秀一波

    把price中19000改为193000

    > db.course.update({"name":"路飞学城-骑士计划"},{$set:{"price.2":19300}}))
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()                                              
    { "_id" : ObjectId("5c3f2c065591b5b80202c911"), "name" : "路飞学城-骑士计划", "price" : [ 19800, 19500, 19300, 18800 ], "other" : { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 } }

    db.course.update({"name":"路飞学城-骑士计划"},{$set:{"price.2":19300}})

    我们用了引用下标的方法更改了数值 , "price.2"代指的是 Array 中第3个元素

    混合用法

    如果price.1小于19800则加200

    > db.course.update({"name":"路飞学城-骑士计划","price.1":{$lt:19800}},{$inc:{"price.1":200}}))
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()                                                                    ":200}})
    { "_id" : ObjectId("5c3f2c065591b5b80202c911"), "name" : "路飞学城-骑士计划", "price" : [ 19800, 19700, 19300, 18800 ], "other" : { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 } }

    发现第二个价格,加了200块!

    把price小于19500的自动补上200

    db.course.update({"name":"路飞学城-骑士计划","price":{$lt:19500}},{$inc:{"price.$":200}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()                                                               
    { "_id" : ObjectId("5c3f2c065591b5b80202c911"), "name" : "路飞学城-骑士计划", "price" : [ 19800, 19900, 19500, 18800 ], "other" : { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 } }

    发现第3个更改了!

    Object 字典

    object字典总玩过把,但是更像是JavaScript中的对象

    1.把other中count改为199

    > db.course.update({"name":"路飞学城-骑士计划"},{$set:{"other.count":199}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()                                                 ":199}})
    { "_id" : ObjectId("5c3f2c065591b5b80202c911"), "name" : "路飞学城-骑士计划", "price" : [ 19800, 19900, 19500, 18800 ], "other" : { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 199 } }

    对了就是在这个对象 打点儿 key 就可以更改数值了 , 要注意的是, 咱们用的 $set 进行修改的,那么就意味着,如果没有"other.count"这个field的话,他会自动创建

    这个用法就到这里了,下面我们玩儿个更深的

    2.混合用法

    如果count小于200那么加10

    > db.course.update({"name":"路飞学城-骑士计划","other.count":{$lt:200}},{$inc:{"other.count":10}}))
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.course.find()                                                                       
    { "_id" : ObjectId("5c3f2c065591b5b80202c911"), "name" : "路飞学城-骑士计划", "price" : [ 19800, 19900, 19500, 18800 ], "other" : { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 209 } }

    这么玩儿完了之后,条件位置的打点儿调用,也尝试过了

    Object的用法就这么多了

    Arry + Object 的用法

    Array + Object 的用法

    首先建立一条document

    复制代码
    # 清空所有数据
    > db.Oldboy.remove({})
    WriteResult({ "nRemoved" : 0 })
    
    # 加入一条数据
    > db.Oldboy.insert({"name":"路飞学城-骑士计划","price":[{"start" : "2018年8月1日","start_time" : "08:30","count" : 150},{"start" : "2018年8月2日","start_time" : "09:30","count" : 160},{"start" : "2018年8月3日","start_time" : "10:30","count" : 170},{"start" : "2018年8月4日","start_time" : "11:30","count" : 180},]})
    WriteResult({ "nInserted" : 1 })
    
    # 查看所有数据
    > db.Oldboy.find()
    { "_id" : ObjectId("5c3f32e387f59c276095f23e"), "name" : "路飞学城-骑士计划", "price" : [ { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 }, { "start" : "2018年8月2日", "start_time" : "09:30", "count" : 160 }, { "start" : "2018年8月3日", "start_time" : "10:30", "count" : 170 }, { "start" : "2018年8月4日", "start_time" : "11:30", "count" : 180 } ] }
    复制代码

    数据比较复杂,大概是这个样子

    复制代码
    {
        "_id" : ObjectId("5b17de9d44280738145722b9"),
        "name" : "路飞学城-骑士计划",
        "price" : [
            {
                "start" : "2018年8月1日",
                "start_time" : "08:30",
                "count" : 150
            },
            {
                "start" : "2018年8月2日",
                "start_time" : "09:30",
                "count" : 160
            },
            {
                "start" : "2018年8月3日",
                "start_time" : "10:30",
                "count" : 170
            },
            {
                "start" : "2018年8月4日",
                "start_time" : "11:30",
                "count" : 180
            }
        ]
    }
    复制代码

    insert的代码要自己写哦,学完一直没怎么练习过,Document添加完成之后

    1. 把count 大于 175 的field  加 15

    > db.Oldboy.update({"price.count":{$gt:175}},{$inc:{"price.$.count":15}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.Oldboy.find()
    { "_id" : ObjectId("5b990b6e430c27444ccdd654"), "name" : "路飞学城-骑士计划", "price" : [ { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 }, { "start" : "2018年8月2日", "start_time" : "09:30", "count" : 160 }, { "start" : "2018年8月3日", "start_time" : "10:30", "count" : 170 }, { "start" : "2018年8月4日", "start_time" : "11:30", "count" : 195 } ] 

    分析一下我们的代码:

    {"price.count":{$gt:175}}, price 明明是个 Array 啊 怎么就直接 打点儿 count 了呢 这里要知道price 打点儿 就是从内部的Object 中找到 count 小于 175 的结果

    {$inc:{"price.$.count":15}} ,  这里就比较好理解了,price里面第 $ (大于175的第一个) 个元素中 count 增加 15

    我们要学会举一反三 $set 如果忘了, 就再来一个例子吧

    2. 把 count 大于 180 的 start 改为 "2018年8月10日"

    > db.Oldboy.update({"price.count":{$gt:180}},{$set:{"price.$.start":"2018年8月10日"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.Oldboy.find()
    { "_id" : ObjectId("5b990b6e430c27444ccdd654"), "name" : "路飞学城-骑士计划", "price" : [ { "start" : "2018年8月1日", "start_time" : "08:30", "count" : 150 }, { "start" : "2018年8月2日", "start_time" : "09:30", "count" : 160 }, { "start" : "2018年8月3日", "start_time" : "10:30", "count" : 170 }, { "start" : "2018年8月10日", "start_time" : "11:30", "count" : 195 } ] }

    不做过多解释了,没学会的翻回去看吧

    到此为止我们MongoDB的操作阶段就已经学习结束了.

    本文参考链接:

    https://www.cnblogs.com/DragonFire/p/9147430.html

    七.选取跳过排序

    我们已经学过MongoDB的find()查询功能了,在关系型数据库中的选取(limit),排序(sort)MongoDB中同样有,而且使用起来更是简单

    首先我们看下添加几条document进来

     View Code

    在有四条Document 根据它们, 对 Limit Skip Sort 分别展开学习 最后来一个 大杂烩

    limit选取

    我们要从这些document中取出多少个

    坐个小栗子,我们只要两条document

    > db.Oldboy.find().limit(2)
    { "_id" : ObjectId("5b990d6b430c27444ccdd655"), "name" : "Python", "price" : "15800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }

    结果是很明显的,很赤裸裸的,很一丝不挂的

    但是我还是要解释一下 : limit(2) 就是选取两条Document, 从整个Collection的第一条 Document 开始选取两条

    如果我们不想从第一条Document开始选取,怎么办呢?

    skip跳过

    我要跳过多少个Document

    做个小例子 : 我要跳过前两个 Document 直接从第三个Document 开始

    > db.Oldboy.find().skip(2)
    { "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "9800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd658"), "name" : "Python架构", "price" : "13800" }

    问题来了,我只想要第二条和第三条怎么处理呢?

     limit + skip

    从这到那儿 的选取

    这就是刚才的问题,一个小栗子:我只想要第二条和第三条怎么处理呢

    > db.Oldboy.find().skip(1).limit(2)
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "9800" }

    国际惯例 : 跳过第一条Document 从第二条开始选取两条 Document

    别着急,还有另一种写法

    > db.Oldboy.find().limit(2).skip(1)
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "9800" }

    两种写法完全得到的结果完全一样但是国际惯例的解释却不同

    国际惯例 : 选取两条Document 但是要 跳过 第一条Document 从 第二条 开始 选取

    绕了半天,都晕了,注意这里特别要注意了!!!!!! 这里的两种写法,一定一定一定要记住一个,因为只要记住一个就行了,完全完全没区别,一个符合中国人的理解,一个是其他国家的理解

    sort排序

    将结果按照关键字排序

    做个小例子 : 将find出来的Document 按照 price 进行 升序 | 降序 排列

    升序

    > db.Oldboy.find().sort({"price":1})
    { "_id" : ObjectId("5b990d6b430c27444ccdd658"), "name" : "Python架构", "price" : "13800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd655"), "name" : "Python", "price" : "15800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "9800" }

    降序

    > db.Oldboy.find().sort({"price":-1})
    { "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "9800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd655"), "name" : "Python", "price" : "15800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd658"), "name" : "Python架构", "price" : "13800" }

    国际惯例 : 按照 price 字段进行升序 , 1 为升序 , -1 为降序

    limit +skip+sort

    一个例子 : 选取第二条第三条 并 按照 price 进行 升序排列

    复制代码
    > db.Oldboy.find()
    { "_id" : ObjectId("5b990d6b430c27444ccdd655"), "name" : "Python", "price" : "15800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "9800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd658"), "name" : "Python架构", "price" : "13800" }
    
    > db.Oldboy.find().skip(1).limit(2).sort({"price":1})
    { "_id" : ObjectId("5b990d6b430c27444ccdd655"), "name" : "Python", "price" : "15800" }
    { "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "19800" }
    复制代码

    问题出现了, 按道理不应该是 9800 然后 19800 吗?

    知识点来喽

    重点 : Sort + Skip + Limit 是有执行优先级的 他们的界别分别是 优先 Sort  其次 Skip 最后 Limt

    Skip + Limit 的优先级 也是先 Skip 再 Limit

    本文参考链接:

    https://www.cnblogs.com/DragonFire/p/9154832.html

  • 相关阅读:
    CGI与FastCGI
    Google Protocol Buffer 的使用和原理
    AMQP协议
    Java 多线程 并发编程
    深入理解HashMap
    Bitmap 位图
    Bloom Filter概念和原理
    BloomFilter–大规模数据处理利器
    java bitmap/bitvector的分析和应用
    Linux iptables 备忘
  • 原文地址:https://www.cnblogs.com/onesea/p/14646326.html
Copyright © 2011-2022 走看看