mongo 连接数据库与本地数据库服务器
use db_name 创建数据库(如果数据库不存在,则创建数据库,否则切换到指定数据库)
db.dropDatabase() 删除数据库
show dbs 查看所有数据库
db.数据库名.insert({_id:1,name:”王小明”}) 向数据库插入数据
db.createCollection("集合名", { capped : true, autoIndexId : true, size : 512000, max : 1000 } )
在数据库中创建创建固定集合“集合名”,整个集合空间大小512000KB,文档最大个数为1000个
capped :是一个布尔类型,true 时创建固定集合,必须指定 size。固定集合指有固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。默认为 false
autoIndexId :也是一个布尔类型,如为 true,自动在_id 字段创建索引。默认为 false ;
size :为固定集合指定一个最大值(以字节 KB 计);
max :指定固定集合中包含文档的最大数量。
db.集合名.insert() 创建集合(注意:一条数据用大括号“ {} ”括起来,多条数据用“ [] ”将所有数据括起来)
db.集合名.find() 查询集合
db.集合名.drop() 删除集合
db.集合名.insert(文档) 插入文档( 如果该集合不在该数据库中,MongoDB 会自动创建该集合并插入文档)
文档:document=({_id:1,
name: '王小明',
sex: '男',
hobbies: ['乒乓球','羽毛球'],
birthday: '1996-02-14'
});
db.person2.update({birthday:"1996-02-14"},{$set:{birthday:"1996"}})
update() 有两个参数,都是对象,中间用逗号“ ,”间隔;
第一个参数表示需要修改的值;
第二个参数用 $set 操作符指向更新后的值。
更改整个集合:
db.集合名.save({
"_id" :1,
"name" : "李小红",
"sex" : "女",
"hobbies" : [
"画画",
"唱歌",
"跳舞"
],
"birthday" : "1996-06-14"
})
注:如果 save() 法也指定了_id,则对文档进行更新;未指定_id则会执行插入功能,MongoDB 默认自动生成一个不重复的_id。
创建集合stu1:
1、
document=([{
name:'张小华',
sex:'男',
age:20,
phone:'12356986594',
hobbies:['打篮球','踢足球','唱歌']
},{
name:'李小红',
sex:'女',
age:18,
phone:'12355487536',
hobbies:['跳舞','唱歌']
}])
2、
db.stu1.insert(document)
3、
db.stu1.find().pretty() .pretty()使输出更整齐
AND 条件
find() 方法可以传入多个键 (key),每个键 (key) 以逗号隔开,即常规 SQL 的 AND 条件。如查询集合 stu1 中年龄为20岁的男性信息:
db.stu1.find({"age":20, "sex":"男"}).pretty()
删除文档数据
删除指定的数据:
db.stu1.remove({'age':20}) //删除年龄为20的数据
删除全部数据(集合并不会删除):
db.remove({})
向数据库导入数据
数据导入工具:mongoimport;
这是 MongoDB 自带的数据导入工具,我们在未连接客户端时使用(前提要启动服务)。
mongoimport -d Testdb1 -c score --type csv --headerline --ignoreBlanks --file test.csv
- -d Testdb1 :指定将数据导入到 Testdb1 数据库;
- -c score :将数据导入到集合 score ,如果这个集合之前不存在,会自动创建一个(如果省略 –collection 这个参数,那么会自动新建一个以 CSV 文件名为名的集合);
- –type csv :文件类型,这里是 CSV;
- –headerline :这个参数很重要,加上这个参数后创建完成后的内容会以 CSV 文件第一行的内容为字段名(导入json文件不需要这个参数);
- –ignoreBlanks :这个参数可以忽略掉 CSV 文件中的空缺值(导入json文件不需要这个参数);
- –file 1.csv :这里就是 CSV 文件的路径了,需要使用绝对路径。
从数据库导出数据
数据导出工具: mongoexport;
- 导出 json 格式文件:
mongoexport -d Testdb1 -c score -o /file.json --type json
-
- -o /file.json :输出的文件路径
/
(根目录下)和文件名; - –type json :输出的格式,默认为 json。
- -o /file.json :输出的文件路径
- 导出 csv 格式的文件:
mongoexport -d Testdb1 -c score -o /file.json --type csv -f "_id,name,age,sex,major"
-
- -f :当输出格式为 csv 时,需要指定输出的字段名。
$all 匹配所有
查询其中所有喜欢“唱歌”和“羽毛球”的人:
- db.hobbies.find({hobbies:{$all:["唱歌","羽毛球"]})
- $all 会查询满足方括号中所有条件的文档,如果只有其中一项满足是不会被查询出来的。
$exists 判断字段是否存在
db.test.find({hobbies:{$exists:true}}).sort({_id:1})
$mod 取模运算
查询 age 取模7等于4的文档:
db.hobbies.find({age:{$mod:[7,4]}})
$in 包含
查询 age =17或 age =20的文档 :
db.hobbies.find({age:{$in:[17,20]}})
$nin 不包含
查询 age !=17且 age !=20的文档:
db.hobbies.find({age:{$nin:[17,20]}})
$size 数组元素个数
可以查询特定长度的数组,比如 hobbies 这一字段,查询有两个爱好的文档:
db.hobbies.find({hobbies:{$size:2}})
查询结果排序
查询结果排序语法如下:
- db.collection.find().sort({_id:1}) #将查询结果按照_id升序排序
- db.collection.find().sort({_id:-1}) #将查询结果按照_id降序排序
$or 条件之间的或查询
$or 表示多个查询条件之间是或的关系,比如查询性别 sex 为 男 或年龄 age 为18的文档信息:
db.student.find({$or:[{sex:"男"},{age:18}]})
$and 条件之间的且查询
$and
表示多个查询条件之间是且的关系,比如查询年龄 age 大于18且小于21(18 < age < 21
)的信息:
db.student.find({$and:[{age:{$gt:18}},{age:{$lt:21}}]})
$not 条件取反查询
$not 用来执行取反操作,比如查询年龄 age 大于等于20岁,然后进行取反(即查询年龄小于20岁的文档):
db.student.find({age:{$not:{$gte:20}}})
正则表达式匹配查询
查询不符合major=
计
*
开头文档:
db.student.find({major:{$not:/^计.*/}})
count() 返回结果集总数
比如返回上一步正则查询到的结果集有几条:
db.student.find({major:{$not:/^计.*/}}).count()
常用聚合管道操作符
常用的几个聚合管道操作符:
操作符 | 作用 |
$project | 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档 |
$match | 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作 |
$limit | 用来限制MongoDB聚合管道返回的文档数 |
$skip | 在聚合管道中跳过指定数量的文档,并返回余下的文档 |
$unwind | 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值 |
$group | 将集合中的文档分组,可用于统计结果 |
$sort | 将输入文档排序后输出 |
注意:以上操作不会修改集合的内容,只是将集合以指定形式输出。
$project 修改文档结构输出
有时候我们并不会用到文档的全部内容,只是使用其中几列,这时候就可以使用 $project 进行操作;或者有时候要重命名键值(列名),也可以使用 $project。
对集合 educoder 进行操作:
- 只输出作者 author 和学习人数 learning_num 信息,
_id
也不要不显示(_id
默认是显示的):
db.educoder.aggregate({$project:{_id:0,author:1,learning_num:1}})
-
- 0 为不显示,非 0 为显示。
重命名字段名(把 learning_num 重命名为 num):
db.educoder.aggregate({$project:{course:1,authoe:1,tags:1,num:'$learning_num'}})
$match 筛选文档输出
有时候我们要在集合中筛选出符合特定条件的文档,这时候使用 $match 便可以很快实现。
只输出作者为“李暾”的文档:
db.educoder.aggregate({$match:{author:'李暾'}})
$limit 限制文档数量输出
有时候集合中文档数量太大,我们只想选取前几行查看一下,这时候就可以用 $limit,输出前2条文档:
db.educoder.aggregate({$limit:2})
$skip 跳过前 n 条文档输出
与 $limit 相反,$skip 是跳过前 n 条文档,显示剩余文档。
将集合 educoder 中的前两条文档跳过,显示剩余文档:
db.educoder.aggregate({$skip:2})
- $skip 接受一个数字 n,表示丢弃结果集中的前 n 个文档;
$limit 与 $skip 可以组合使用,:
- db.educoder.aggregate([{$skip:1},{$limit:2}])
- #跳过第一条,显示前两条,也就是显示第2-3条文档
- db.educoder.aggregate([{$limit:2},{$skip:1}])
- #显示前两条,跳过第一条,也就是显示第2条文档
$unwind 拆分数组类型字段
将 educoder 中的 tags 字段拆分成多条,每条包含数组中的一个值:
db.educoder.aggregate({$unwind:'$tags'})
$group 分组输出
该操作比较常用,因为文档分组后利于我们的统计。比如,按照作者分组我们就可以统计出该集合总共有几个作者。
在集合 educoder 中,按作者分组:
db.educoder.aggregate({$group:{_id:'$author'}})
$sort 排序输出
按照学习人数 learning_num 降序排序输出文档:
db.educoder.aggregate({$sort:{learning_num:-1}})
- -1 代表降序排序, 1 代表升序排序。
聚合表达式
常用的几个聚合表达式:
表达式 | 用法 |
$sum | 计算总和 |
$avg | 计算平均值 |
$min | 获取集合中所有文档对应值的最小值 |
$max | 获取集合中所有文档对应值的最大值 |
$push | 在结果文档中插入值到一个数组中 |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本 |
$first | 根据资源文档的排序获取第一个文档数据 |
$last | 根据资源文档的排序获取最后一个文档数据 |
现在我们通过aggregate()方法来获取每个作者拥有的实训数量,命名为:num_course:
db.educoder.aggregate([{$group:{_id:'$author',num_course:{$sum:1}}}])
- 先通过聚合管道操作符$group将author字段数据分组;
- $sum:1的含义:如果前面的情况出现一次,就加1,如果后面为$sum:2,那么前面条件每满足一次就加2;
- 通过aggregate()方法来获取每个作者的实训学习总人数learning_sum:
db.educoder.aggregate([{$group:{_id:'$author',learning_sum:{$sum:'$learning_num'}}}])
了解索引
- 什么是索引:
索引本质上是树,最小的值在最左边的叶子上,最大的值在最右边的叶子上,使用索引可以提高查询速度(而不用全表扫描)。
- 索引的原理:
对某个键按照升续或降续创建索引,查询时首先根据查询条件查找到对应的索引条目,然后找到索引条目对应的文档指针(文档在磁盘上的存储位置),根据文档指针再去磁盘中找到相应的文档,整个过程不需要扫描全表,速度比较快。
每个文档被插入集合时,如果没有给它指定索引_id
,MongoDB 会自动给它创建一个默认索引_id
,是个 ObjectId 对象
索引的分类
MongoDB 支持多种类型的索引,主要有以下几种类型:
索引类型 | 用途 |
包括单字段索引(Single Field Index) | 针对某一键 key 创建了单字段索引,其能加速对 key 字段的各种查询请求,是最常见的索引形式,MongoDB 默认创建的 id 索引也是这种类型。 |
复合索引 (Compound Index) | 复合索引是单字索引的升级版本,它针对多个字段联合创建索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,依次类推。 |
多 key 索引 (Multikey Index) | 当索引的字段为数组时,创建出的索引称为多 key 索引。 |
哈希索引(Hashed Index) | 按照某个字段的hash值来建立索引,目前主要用于 MongoDB Sharded Cluster 的 Hash 分片,哈希索引只能满足字段完全匹配的查询,不能满足范围查询等。 |
地理位置索引(Geospatial Index) | 能很好的解决 O2O 的应用场景,比如:查找附近的美食、查找某个区域内的车站等。 |
文本索引(Text Index) | 能解决快速文本查找的需求,比如有一个博客文章集合,需要根据博客的内容来快速查找,则可以针对博客内容建立文本索引。 |
索引基本操作
创建索引(单字段索引)
db.person.createIndex({key:1})
-
- key :要创建索引的键;
- 如果为 1 说明是按照升序创建索引,而如果为 -1,则是按降序创建索引。
查询索引
- 查询集合索引:
db.person.getIndexes()
查询系统全部索引:
db.system.indexes.find()
删除索引
- 通过指定索引名称删除该索引:
db.person.dropIndex("ageIdx")
通过指定集合删除集合中的全部索引:
db.person.dropIndexes()
注:默认索引_id
不会且不能被删除
创建复合索引
和创建单字段索引的方法差不多,只是选取了多个键一同作为索引,中间以逗号隔开:
db.person.createIndex({age: 1, name: 1})
创建多 key 索引
当索引的字段为数组时,创建出的索引称为多 key 索引,多 key 索引会为数组的每个元素建立一条索引,比如 person 集合加入一个 habbit 字段(数组)用于描述兴趣爱好:
{name : '王小明', age : 19, habbit: ['football', 'runnning']}
需要查询有相同兴趣爱好的人就可以利用 habbit 字段的多 key 索引。
db.person.createIndex( {habbit: 1} ) // 升序创建多key索引
db.person.find({habbit: 'football'}) //查找喜欢足球的人
创建哈希索引
创建命令如下:
db.person.createIndex( { _id: 'hashed' } )
文本索引的创建与使用
- 什么时候使用文本索引;
假如我们用 Mongodb 存储了很多博客文章,那么如何快速找到所有关于 mongodb 这个主题的文章呢?这时候就要用到文本搜索了。
有文章集合 collection,如下:
-
- {
- title: 'enjoy the mongodb articles on educoder',
- tags: [
- 'mongodb',
- 'educoder'
- ]
- }
- 创建文本索引命令,如下:
db.collection.createIndex({ title: 'text'})
-
- 创建全文本索引的字段必须为 string 格式;
- 每个集合只支持一个文本索引。
也可以创建多个字段的 text,下面的示例在字段主题和注释上创建一个文本索引:
- db.collection.createIndex(
- {
- title:'text',
- tags:'text'
- }
- )
使用文本索引;
现在我们已经创建了 title 的索引,我们来搜索一下含有 educoder.net 的文章:
db.collection.find({$text:{$search:'educoder.net'}})
- search 后的关键词可以有多个,关键词之间的分隔符可以是多种字符,例如空格、下划线、逗号、加号等,但不能是
-
和\
,因为这两个符号会有其他用途。搜索的多个关键字是 or 的关系,除非你的关键字包含-
; - 匹配时不是完整的单词匹配,相似的词也可以匹配到;
删除文本索引;
- 通过命令获取索引名:
db.collection.getIndexes()
- 删除命令:
db.collection.dropIndex('title_text')
GeoJson 数据
并不是所有文档都可以创建地理位置索引,只有拥有特定格式的文档才可以创建。
如果我们用的是 2dsphere 索引,那么插入的应该是 GeoJson 数据。GeoJson 的格式如是: { type: ‘GeoJSON type’ , coordinates: ‘coordinates’ }
- type :指的是类型,可以是 Point (本例中用的)、LineString、 Polygon 等;
- coordinates :指的是一个坐标数组。
我们有如下几个位置的坐标信息(具体详情如图1所示),先把它们写入集合 locations 中。
- db.locations.insert({_id:1,name:'长沙站',location:{type:'Point',coordinates:[113.018987,28.201215]}})
- db.locations.insert({_id:2,name:'湖南师范大学',location:{type:'Point',coordinates:[112.946045,28.170968]}})
- db.locations.insert({_id:3,name:'中南大学',location:{type:'Point',coordinates:[112.932175,28.178291]}})
- db.locations.insert({_id:4,name:'湖南女子学院',location:{type:'Point',coordinates:[113.014675,28.121163]}})
创建地理位置索引
有了规范的文档后,我们就可以使用以下命令,在 location 键上创建一个地理位置索引:
db.locations.createIndex({location:'2dsphere'})
- 2d :平面坐标索引,适用于基于平面的坐标计算,也支持球面距离计算,不过官方推荐使用 2dsphere 索引;
- 2dsphere :几何球体索引,适用于球面几何运算;
- 默认情况下,地理位置索引会假设值的范围是从−180到180(根据经纬度设置)。
地理位置索引的使用
查询命令:
- db.runCommand({
- geoNear:'locations',
- near:{type:'Point',coordinates:[113.018987,28.201215]},
- spherical:true,
- minDistance:1000,
- maxDistance:8000
- })
- geoNear :我们要查询的集合名称;
- near :就是基于那个点进行搜索,这里是我们的搜索点“长沙站”;
- spherical :是个布尔值,如果为 true,表示将计算实际的物理距离,比如两点之间有多少 km,若为 false,则会基于点的单位进行计算 ;
- minDistance :搜索的最小距离,这里的单位是米 ;
- maxDistance :搜索的最大距离。