docker 安装MongoDB
//查找MongoDB镜像
docker search mongo
//拉取镜像
docker pull mongo
//查看下载来的MongoDB
docker inspect mongo:latest
编辑docker-compose.yml文件
[root@localhost mongodb]# more docker-compose.yml
version: '2'
services:
mongodb:
image: mongo:latest
volumes:
- "./configdb:/data/configdb"
- "./db:/data/db"
ports:
- "27017:27017"
docker-compose up -d
启动即可
启动MongoDB
mongod -dbpath=/root/mongodb/mongodb/data/db -port=27017
启动之后可以用 mongo
命令连接MongoDB
插入数据:
db.runoob.insert({x:10})
直接将数据保存到runoob
集合中,无需预先创建
db.runoob.find()
查找数据
db.runoob.findOne()
查找集合中的一个元素
show dbs
显示所有的数据库列表
db
显示当前使用的数据库
use local
将使用的数据库切换到local
db.dropDatabase()
删除当前的数据库
-
几个特殊的保留数据库
admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
文档以BSON
的格式存储,文档有一下几个注意点:
- 文档中的键/值对是有序的
- 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)
- MongoDB区分类型和大小写。
- MongoDB的文档不能有重复的键。
- 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
- BSON 与JSON的区别:
BSON是在JSON上改造优化而成,主要有以下3点改进:
- 更快的遍历速度
将json的每一个元素的长度存在元素的头部,这样只需要读取到元素长度就能直接seek到指定的点上进行读取了,从而加快了文档的遍历 - 操作更简易
对json来说,数据存储是无类型的,比如你要修改基本一个值,从9到10,由于从一个字符变成了两个,所以可能其后面的所有内容都需要往后移一位才可以。
而使用bson,你可以指定这个列为数字列,那么无论数字从9长到10还是100,我们都只是在存储数字的那一位上进行修改,不会导致数据总长变大。
当然,在mongoDB中,如果数字从整形增大到长整型,还是会导致数据总长变大的 - 增加了额外的数据类型
增加了“byte array”数据类型。这使得二进制的存储不再需要先base64转换后再存成json,大大减少了计算开销和数据大小
- 总之:
数据结构:
json是像字符串一样存储的,bson是按结构存储的(像数组 或者说struct)
存储空间
bson>json
操作速度
bson>json。比如,遍历查找:json需要扫字符串,而bson可以直接定位
修改:
json也要大动大移,bson就不需要。
-
capped collections 固定大小的collection
有很高的性能以及队列过期的特性(过期按照插入的顺序),非常适合类似记录日志的功能,必须要显式的创建一个capped collection, 指定一个collection的大小,单位是字节,在capped collection能进行更新,然而,对象不能增加存储空间。如果增加,更新就会失败,数据库不允许进行删除。使用drop()方法删除collection所有的行。删除之后必须再显式的创建
-
MongoDB数据类型
数据类型 | 描述 |
---|---|
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 JavaScript 代码。 |
Regular expression | 正则表达式类型。用于存储正则表达式。 |
-
ObjectID 组成
> var newObject = ObjectId()
> newObject.getTimestamp() //得到创建时间
ISODate("2018-06-09T13:18:48Z")
> newObject //查看对象值
ObjectId("5b1bd3b8b4852af9d8e13020")
> newObject.str //转换为字符串
5b1bd3b8b4852af9d8e13020
- 日期:
> var mydate1 = new Date() //格林尼治时间
> mydate1
ISODate("2018-06-09T13:23:39.243Z")
> var mydate2 = ISODate()
> mydate2
ISODate("2018-06-09T13:23:56.868Z")
> typeof mydate1 //查看类型
object
> var mydate1str = mydate1.toString() //转成字符串
> mydate1str
Sat Jun 09 2018 21:23:39 GMT+0800 (CST)
> typeof mydate1str
string
> Date() //查看当前日期
Sat Jun 09 2018 21:24:53 GMT+0800 (CST)
-
连接的标准URL格式
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
例子:
//连接到test数据库
mongodb://admin:123456@localhost/test
//连接 replica pair, 服务器1为example1.com服务器2为example2。
mongodb://example1.com:27017,example2.com:27017
//连接 replica set 三台服务器, 写入操作应用在主服务器 并且分布查询到从服务器。
mongodb://host1,host2,host3/?slaveOk=true
//直接连接第一个服务器,无论是replica set一部分或者主服务器或者从服务器。
mongodb://host1,host2,host3/?connect=direct;slaveOk=true
//安全模式连接到localhost:
mongodb://localhost/?safe=true
//以安全模式连接到replica set,并且等待至少两个复制服务器成功写入,超时时间设置为2秒。
mongodb://host1,host2,host3/?safe=true;w=2;wtimeoutMS=2000
-
MongoDB 数据操作
-
集合
- 创建集合
db.createCollection("runoob")
db.col2.insert({"name":"zzj"})
//创建固定集合 mycol,整个集合空间大小 6142800 KB, 文档最大个数为 10000 个。
> db.createCollection("mycol", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )
{
"note" : "the autoIndexId option is deprecated and will be removed in a future release",
"ok" : 1
}
> db.mycol.drop() //删除集合
true
- 查看所有的集合
show collections
- 删除集合
db.mycol.drop()
-
文档
//切换数据库
use test
//保存数据
db.test.insert({"name":"zzj","age":18})
//查找集合
db.test.find();
//定义一个文档
var document=({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
});
db.col.insert(document);
db.col.find();
//3.2版本后可以插入一条文档数据
var document=db.collection.insertOne({"a":"test"});
document
//3.2版本后一次插入多个文档数据
var res = db.collection.insertMany([{"b":3},{"c":4}]);
res
- 修改文档
//文档更新
db.collection.update(
{"name":"zzj100001"}, //相当于where条件
{"$set":{"age":"19"}}, // 相当于set
{
"upsert":true, //是否新增,true表示没有找到会新增一行,默认为false
"multi":true //true更新找到的全部记录,false为一条记录
}
);
db.collection.find({"name": /zzj/});
//更新整个文档
db.collection.save(
{
"_id" : ObjectId("5b1f3689ca00cba7f8960a2b"),
"name" : "zzj100003",
"age" : "19",
"parents":[
{"name":"zzold"},
{"name":"zzyong"}
]
}
);
- 删除文档
//删除整个集合数据
db.col.remove({});
db.col.find();
db.collection.find({"b":{"$gt":3}}).count();
//删除一部分(指定条件)数据
db.collection.remove(
{"b":{"$gt":3}},
{"justOne":true} //true只删除匹配到的一个
);
db.collection.remove(
{"b":{"$gt":3}},
{"justOne":false} //false 删除匹配到的全部数据
);
//remove方法已经过时,现在推荐deleteOne,deleteMany
//全部删除
db.col.deleteMany({});
db.collection.find({"b":{"$lte":3}}).count();
//删除一个
db.collection.deleteOne({"b":{"$lte":3}});
//删除指定条件的
db.collection.deleteMany({"b":{"$lte":3}});
- 查询文档
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key>:<value>} | db.col.find({"by":"菜鸟教程"}).pretty() | where by = 'xxx' |
小于 | {<key>:{$lt:<value>}} | db.col.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
小于或等于 | {<key>:{$lte:<value>}} | db.col.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key>:{$gt:<value>}} | db.col.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
大于或等于 | {<key>:{$gte:<value>}} | db.col.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key>:{$ne:<value>}} | db.col.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
//查找 collection 集合中name 包含 zzj的文档
db.collection.find({"name":/zzj/});
// ---------and-----------
//查找 collection 集合中name 包含 zzj并且年龄大于"18"的文档,注意"18"的类型
db.collection.find({"name":/zzj/,"age":{"$gte":"18"}});
//----------or------------
//查找 collection 集合中 name等于zzj1或者年龄等于18的数据
db.collection.find({"$or":[
{"name":"zzj1"},
{"age":18}
]});
db.collection.find({"b":{"$gt":3}});
//查找 collection 集合中 b 大于3 或者 (名字等于zzj1并且年龄为18) 的数据
db.collection.find({
"b":{"$gt":3},
"$or":[
{"name":"zzj1"},
{"age":18}
]
});
db.col.find({"likes": {$gt:50},
$or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]
})
//只显示name和age字段,不显示_id一段
db.collection.find(
{"b":{"$gt":3}},
{"name":1,"age":1,"_id":0}
);
//不显示age和_id字段
//需要注意的是如果设置 0 的话那就都要设置0,设置1(可见)那就都要设置1,_id是个例外,哪个用它都可以
db.collection.find(
{"b":{"$gt":3}},
{"age":0,"_id":0}
);
//查找集合中age字段为String类型(等于2)
//类型值参考http://www.runoob.com/mongodb/mongodb-operators-type.html
db.collection.find({"age": {"$type":2}});
//跳过5行,返回后面的50行
db.collection.find({"c":{"$gt":3}}).skip(5).limit(50);
//排序,1为升序,-1为降序
db.collection.find().sort({"age":-1}).limit(5);
//分析查询计划
db.collection.find().sort({"age":-1}).limit(5).explain();
db.collection.find().count();
- 创建索引
//创建索引,1为升序,-1为降序
db.collection.createIndex({"name":1},{"name":"col_1"})
//后面这个name 指定索引名称
db.collection.createIndex({"name":-1},{"name":"col_-1"})
//查看集合collection所有的索引信息
db.collection.getIndexes();
//创建唯一索引,数据不符合会报错
db.collection.createIndex({"age":1},{"unique":true,"background":true});
//创建唯一索引,是否删除重复记录,指定 true 创建唯一索引,默认值为 false会报错.
db.collection.createIndex({"age":1},{"unique":true,"background":true,"dropDups":true,"name":"age_1"});
//删除集合 collection 中名称为 col_-1 的索引
db.collection.dropIndex("col_-1");
//查看索引总大小
db.collection.totalIndexSize();
//删除集合中所有的索引
db.collection.dropIndexes()
db.collection.insert(
{
"post_text": "enjoy the mongodb articles on Runoob",
"tags": [
"mongodb",
"runoob"
]
}
);
//创建全文检索索引
db.collection.ensureIndex({post_text:"text"})
//全文检索,这个搜索 runoob有,搜索 runoo就没有
db.collection.find({$text:{$search:"runoob"}}) //找得到
db.collection.find({$text:{$search:"runoo"}}) //没找到
- 聚合
//聚合
db.mycol.insertMany([
{
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
}
]);
//以字段 by_user分组,汇总条数
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
//以字段 by_user分组,将 likes 字段的值累加起来
//类似 select by_user, count(*) from mycol group by by_user
db.mycol.aggregate([
{"$group":{"_id":"$by_user","sum_value" :{"$sum":"$likes"}}}
]);
//平均值
db.mycol.aggregate([
{"$group":{"_id":"$by_user","sum_value" :{"$avg":"$likes"}}}
]);
//最小值
db.mycol.aggregate([
{"$group":{"_id":"$by_user","sum_value" :{"$min":"$likes"}}}
]);
//最大值
db.mycol.aggregate([
{"$group":{"_id":"$by_user","sum_value" :{"$max":"$likes"}}}
]);
//push 将结果文档插入值到一个数组中,这个结果返回的Url是个数组,不会去重
db.mycol.aggregate([
{"$group":{"_id":"$by_user","url":{"$push":"$url"}}}
]
)
//和push一样,Url是个数组,但是会去重
db.mycol.aggregate([
{"$group":{"_id":"$by_user","url":{"$addToSet":"$url"}}}
]
)
//第一个
db.mycol.aggregate([
{"$group":{"_id":"$by_user","sum_value" :{"$first":"$likes"}}}
]);
//最后一个
db.mycol.aggregate([
{"$group":{"_id":"$by_user","sum_value" :{"$last":"$likes"}}}
]);
数据类型
参考
springboot MongoDB源码示例参考
国外的一个例子
另一个java的MongoTemplate例子