一.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 Files\MongoDB\Server\3.4\bin"

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

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

windows 10 一路到底的"确定"

windows 7 在这里需要注意的是,Path路径移动到最后,输入:"  ;C:\Program Files\MongoDB\Server\3.4\bin  " 一定要带上 "  ;  " 哦

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

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

我们来试一下成果吧

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

那我们来创建一个" C:\data\db\ "的目录吧

好了目录已经有了,再次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" 代指的是时间戳,这条数据的产生时间
"" 代指某台机器的机器码,存储这条数据的机器标号
"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中 加上关键字,就变成了修改器

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

准备基础数据

# 清空数据
> db.course.remove({})
WriteResult({ "nRemoved" : 5 }) # 插入三条数据
> db.course.insertMany([{"name":"Linux","score":100,"test_list":[2,3,4]},{"name":"Python","score":80,"test_list":[1,2,3,4,5]},{"name":"Go","score":59,"test_list":[1,2,3,4,5]}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5c3f261a5591b5b80202c90e"),
ObjectId("5c3f261a5591b5b80202c90f"),
ObjectId("5c3f261a5591b5b80202c910")
]
} # 查看所有数据
> db.course.find()
{ "_id" : ObjectId("5c3f261a5591b5b80202c90e"), "name" : "Linux", "score" : 100, "test_list" : [ 2, 3, 4 ] }
{ "_id" : ObjectId("5c3f261a5591b5b80202c90f"), "name" : "Python", "score" : 80, "test_list" : [ 1, 2, 3, 4, 5 ] }
{ "_id" : ObjectId("5c3f261a5591b5b80202c910"), "name" : "Go", "score" : 59, "test_list" : [ 1, 2, 3, 4, 5 ] }

首先看个例子:  现在把 "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进来

# 清空所有数据
> db.Oldboy.remove({})
WriteResult({ "nRemoved" : 1 }) # 插入多条数据
> db.Oldboy.insertMany([{"name" : "Python","price" : ""},{"name" : "骑士计划","price" : ""},{"name" : "Linux","price" : ""},{"name" : "Python架构","price" : ""},])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5b990d6b430c27444ccdd655"),
ObjectId("5b990d6b430c27444ccdd656"),
ObjectId("5b990d6b430c27444ccdd657"),
ObjectId("5b990d6b430c27444ccdd658")
]
} # 查看所有数据
> db.Oldboy.find()
{ "_id" : ObjectId("5b990d6b430c27444ccdd655"), "name" : "Python", "price" : "" }
{ "_id" : ObjectId("5b990d6b430c27444ccdd656"), "name" : "骑士计划", "price" : "" }
{ "_id" : ObjectId("5b990d6b430c27444ccdd657"), "name" : "Linux", "price" : "" }
{ "_id" : ObjectId("5b990d6b430c27444ccdd658"), "name" : "Python架构", "price" : "" }

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

limit选取

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

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

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

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

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

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

skip跳过

我要跳过多少个Document

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

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

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

limit + skip

从这到那儿 的选取

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

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

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

别着急,还有另一种写法

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

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

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

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

sort排序

将结果按照关键字排序

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

升序

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

降序

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

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

limit +skip+sort

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

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

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

知识点来喽

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

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

本文参考链接:

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

mongoDB的基本用法的更多相关文章

  1. MongoDB高级查询用法大全

    转载 http://blog.163.com/lgh_2002/blog/static/440175262012052116455/ 详见官方的手册: http://www.mongodb.org/d ...

  2. mongodb聚合管道用法

    基本用法 db.collection.aggregate( [ { <stage> }, ... ] ) stage如下 名称 描述 $addFields 将新的字段添加到文档中,输出的文 ...

  3. mongoDB 特别指令用法

    http://apluck.iteye.com/blog/1176160 a.   修改collection集合字段名 参见:http://www.mongodb.org/display/DOCS/U ...

  4. mongoDB 索引的用法

    http://www.cnblogs.com/lipan/archive/2011/03/28/1997202.html MongoDB中的索引其实类似于关系型数据库,都是为了提高查询和排序的效率的, ...

  5. mongodb 查询的用法

    想要在C#中使用MongoDB,首先得要有个MongoDB支持的C#版的驱动.C#版的驱动貌似有很多种,如官方提供的samus. 实现思路大都类似.这里我们用官方提供的mongo-csharp-dri ...

  6. MongoDB数据库基本用法

    show dbs:显示数据库列表  show collections:显示当前数据库中的集合(类似关系数据库中的表)  show users:显示用户 use <db name>:切换当前 ...

  7. Mongodb查询的用法,备注防止忘记

    最近在用这个东西,为防止忘记,记下来. 集合简单查询方法 mongodb语法:db.collection.find()  //collection就是集合的名称,这个可以自己进行创建. 对比sql语句 ...

  8. MongoDB的一些用法(转藏)

    MongoDB是目前工作中经常使用到的NoSQL数据库. 本博客只记录相关理论知识和技巧,涉及到实践的部分都会单开Blog来记录实践过程. ------------------------------ ...

  9. MongoDB的MapReduce用法及php示例代码

    MongoDB虽然不像我们常用的mysql,sqlserver,oracle等关系型数据库有group by函数那样方便分组,但是MongoDB要实现分组也有3个办法: * Mongodb三种分组方式 ...

随机推荐

  1. 移动端placeholder不能垂直居中解决方案

    1.问题描述 问题如图:手机端placeholder文字偏上,垂直方向不居中,input光标显示偏上解决IE下不支持placeholder属性 2.解决方案 css .phoneNumber inpu ...

  2. java 十六周总结

  3. str类型内置方法

    目录 str类型内置方法 用途 定义方式 常用操作和内置方法 优先掌握 需要掌握 了解 存一个值or多个值 有序or无序 可变or不可变 强化训练 str类型内置方法 用途 字符串数字.字母.下划线组 ...

  4. Java核心技术 卷一 复习笔记(乙

    1.字符串从概念上讲,Java字符串就是Unicode字符序列.Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,叫String. 每个用双引号括起来的字符串都是 String ...

  5. PAT 1133 Splitting A Linked List

    Given a singly linked list, you are supposed to rearrange its elements so that all the negative valu ...

  6. UVALive 6510 Stickers

    Stickers Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ...

  7. 又见GCD

    Problem Description 有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b.若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c.   Input ...

  8. poj——2084  Game of Connections

    Game of Connections Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 8664   Accepted: 42 ...

  9. 简单的事件处理类Event

    class Event{ constructor(){ this.handlers=[] } on(type,fn){ //订阅事件 if(!this.handlers[type]){ this.ha ...

  10. nodejs fs.open

    fs.open(path, flags, [mode], [callback(err, fd)])是 POSIX open 函数的封装,与 C 语言标准库中的 fopen 函数类似.它接受两个必选参数 ...