简介
- MongoDB 是一个基于分布式文件存储的数据库,由 C++ 编写,支持的数据结构松散,是类似于 JSON 的 BSON(Binary JSON) 格式,因此可以存储比较复杂的数据类型。其最大特点是支持的查询语言非常强大,语法类似于面向对象的查询语言,基本上可实现类似关系数据库单表查询的绝大部分功能,且支持对数据建立索引。
术语
MongoDB | SQL | 说明 |
---|---|---|
database | database | 数据库 |
collection | table | 集合 & 表 |
document | row | 文档 & 行记录 |
field | column | 域 & 字段 |
primary key | primary key | 主键、MongoDB 自动将 _id 设置为主键 |
index | index | 索引 |
命令行操作
库、表操作
查询所有数据库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
使用数据库
> use admin
switched to db admin
创建数据库、在 MongoDB 中,数据库是自动创建的,通过 use 切换到新数据库中,进行插入数据即可自动创建数据库
> use testdb
switched to db testdb # 此时并未创建成功、需要向库中插入一条数据才会真正创建
删除数据库:以删除 testdb 为例
> db.dropDatabase() # 执行删除并响应:{"dropped" : "testdb", "ok" : 1}
查看表(show tables 和 show collections 都可以)
> show tables # 响应出所有表名
> show collections # 响应出所有表名
删除 user 表
> db.user.drop() # 删除成功返回 true,否则返回 false。
增删改查
增(insert)
# 语法:db.COLLECTION_NAME.insert(document)
# 插入数据
> db.user.insert({id:1,username:'zhangsan',age:20})
WriteResult({ "nInserted" : 1 })
# 查询数据
> db.user.find() # 罗列出user表中所有文档
改(update)
db.collection.update(
<query>, # 查询条件、类似 where 后面的
<update>, # 跟新操作、类似 set 后面的
[
upsert: <boolean>, # 当数据不存在的是否进行插入,默认 false 不插入
multi: <boolean>, # 只更新找到的第一条记录,默认 false,改为 true 后会更新全部匹配到的数据
writeConcern: <document> # 可选参数、可定义抛出异常的级别
]
)
# 更新数据
> db.user.update({id:1},{$set:{age:22}})
# 注意:如下操作会删除除了 age 以外的其它字段
> db.user.update({id:1},{age:25})
# 注意:更新不存在的字段会新增字段
> db.user.update({id:1},{sex:25})
# 设置第一个参数为 true、此时 id = 3 的记录不存在、则会新增一条记录
> db.user.update({id:3},{$set:{sex:1}},true)
删(remove)
db.collection.remove(
<query>, # 查询条件、类似 where 后面的
{
justOne: <boolean>, # 删除一个 or 全部匹配的,设置为 true or 1 则只删除一个,默认 false 删除所有匹配文档
writeConcern: <document> # 可选参数、可定义抛出异常的级别
}
)
# 删除数据
> db.user.remove({age:12})
# 删除数据:只删一条
> db.user.remove({age:12}, true)
# 删除所有数据
> db.user.remove({})
# 官方推荐:使用 deleteOne() 与 deleteMany() 进行删除数据操作。
> db.user.deleteOne({id:1}) # 删一个
> db.user.deleteMany({}) # 删全部
查(find)
db.user.find(
[query], # 可选,使用查询操作符指定查询条件
[fields] # 可选,选择返回指定字段
)
> db.user.find({"age":20}).pretty(); # 等于、使用 pretty() 会以格式化的方式来显示所有文档
> db.user.find({"age":{$ne:30}}).pretty(); # 不等于
> db.user.find({"age":{$lt:30}}).pretty(); # 小于
> db.user.find({"age":{$lte:30}}).pretty(); # 小于等于
> db.user.find({"age":{$gt:30}}).pretty(); # 大于
> db.user.find({"age":{$gte:30}}).pretty(); # 大于等于
> db.user.find().find({age:{$lt:20}, id:{$gt:20}}); # AND 语句、查询 id > 20 and age < 20 的
> db.user.find({$or:[{id:1},{id:2}]}); # OR 查询、查询 id=1 or id=2
> db.user.find(); # 查询全部
> db.user.find().count(); # 查出多少条数据
> db.user.find({}, {id:1, username:1}); # 只查 ID 和 USERNAME
> db.user.find().limit(2).skip(1); # 分页查询、跳过第一条、查询2条数据
> db.user.find().sort({id, -1}); # 按照ID倒序排列、-1:倒序、1:正序
索引
查看索引、1:表示升序创建索引,-1:表示降序创建索引
> db.user.getIndexes();
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "testdb.user"
}
]
查看索引、1:表示升序创建索引,-1:表示降序创建索引查看索引大小,单位:字节
> db.user.totalIndexSize()
创建索引
> db.user.createIndex({'age':1});
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
删除索引
> db.user.dropIndex("age_1");
删除除了_id之外的索引
> db.user.dropIndexes();
###### 创建联合索引
> db.user.createIndex({'age':1, 'id':-1});
执行计划
插入 1000 条数据
> for(var i=1;i<1000;i++)db.user.insert({id:100+i,username:'name_'+i,age:10+i});
查询执行计划
> db.user.find({age:{$gt:100},id:{$lt:200}}).explain();
说明: 关注 winningPlan 字段来查看索引使用情况
COLLSCAN:全表扫描、IXSCAN:索引扫描、FETCH:根据索引去检索文档、SHARD_MERGE:合并分片结果、IDHACK:针对_id进行查询
JAVA API 操作
import com.mongodb.client.*;
import org.bson.Document;
import java.util.function.Consumer;
public class MongoDBDemo {
public static void main(String[] args) { // 建立连接
MongoClient mongoClient = MongoClients.create("mongodb://172.16.55.185:27017");
// 选择数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("testdb");
// 选择表
MongoCollection<Document> userCollection = mongoDatabase.getCollection("user");
// 查询数据
userCollection.find().limit(10).forEach((Consumer<? super Document>)
document -> {
System.out.println(document.toJson());
});
mongoClient.close();
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/testdb
@Autowired
private MongoTemplate mongoTemplate;
public void savePerson(Person person) {
this.mongoTemplate.save(person);
}
public List<Person> queryPersonListByName(String name) {
Query query = Query.query(Criteria.where("name").is(name));
return this.mongoTemplate.find(query, Person.class);
}
public List<Person> queryPersonPage(Integer page, Integer rows) {
Query query = new Query().limit(rows).skip((page - 1) * rows);
return this.mongoTemplate.find(query, Person.class);
}
public List<Person> queryPersonPage(Integer page, Integer rows) {
Criteria criteria = new Criteria().orOperator(fromList, toList);
PageRequest pageRequest = PageRequest.of(page - 1, rows, Sort.by(Sort.Direction.ASC,"send_date"));
Query query = new Query(criteria).with(pageRequest);
return this.mongoTemplate.find(query, Message.class);
}
public UpdateResult update(Person person) {
Query query = Query.query(Criteria.where("id").is(person.getId()));
Update update = Update.update("age", person.getAge());
return this.mongoTemplate.updateFirst(query, update, Person.class);
}
public DeleteResult deleteById(String id) {
Query query = Query.query(Criteria.where("id").is(id));
return this.mongoTemplate.remove(query, Person.class);
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "message")
@Builder
public class Message {
@Id
private ObjectId id;
private String msg;
/**
* 消息状态,1-未读,2-已读
*/
@Indexed
private Integer status;
@Field("send_date")
@Indexed
private Date sendDate;
@Field("read_date")
private Date readDate;
@Indexed
private User from;
@Indexed
private User to;
}
安装
docker 部署 mongodb 并操作
# 拉取镜像
docker pull mongo:3.2
# 创建容器
docker create --name mongodb -p 27017:27017
-v /usr/local/mongo/db:/data/db
-v /usr/local/mongo/configdb:/data/configdb
-v /usr/local/mongo/log:/data/log
mongo:3.2
# 启动容器
docker start mongodb
# 进入容器
docker exec -it mongodb /bin/bash
# 使用MongoDB客户端进行操作
mongo
# 创建用户
db.createUser({user:"admin",pwd:"password",roles:["root"]})
> db.createUser({ user:'healthy',pwd:'mongo@999',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]});
# 使用上面创建的用户信息进行连接。
> db.auth('admin', '123456')
配置文件介绍
# 配置配置文件
vim /usr/local/mongo/configdb/mongodb.conf
#端口
port=27017
#数据库文件存放目录
dbpath=/data/db
#日志文件存放路径
logpath=/data/log
#使用追加方式写日志
logappend=true
#以守护线程的方式运行,创建服务器进程
fork=true
#最大同时连接数
maxConns=100
#不启用验证
#noauth=true
#每次写入会记录一条操作日志
journal=true
#存储引擎有mmapv1、wiredTiger、mongorocks
storageEngine=wiredTiger
#访问IP
bind_ip=0.0.0.0
#用户验证
#auth=true
开启远程连接
# 以 healthy 身份进入 mongodb
docker exec -it mongodb mongo healthy
# 开启远程
# 方式一:注释掉 # bindIp: 127.0.0.1
# 方式二:改成为 # bindIp: 0.0.0.0
操作
> show dbs;
2021-07-01T05:40:22.673+0000 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
"code" : 13
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:781:19
shellHelper@src/mongo/shell/utils.js:671:15
@(shellhelp2):1:1
> use admin
switched to db admin
> db.createUser({user:'healthy',pwd:'mongolive999',roles:[{role:'root', db:'message'},"readWriteAnyDatabase"]});
Successfully added user: {
"user" : "healthy",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
},
"readWriteAnyDatabase"
]
}
> db.auth('healthy', 'mongolive999')
1
> show dbs
admin 0.000GB
local 0.000GB
> db.changeUserPassword('healthy','mongolive999');
> db.updateUser("healthy",{roles:[ {role:"userAdminAnyDatabase",db:"admin"} ]})
> show users
{
"_id" : "admin.healthy",
"user" : "healthy",
"db" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
> db.grantRolesToUser("healthy", [{role:"dbOwner", db:"healthy"},{role:"root", db:"admin"}]);
> show users
{
"_id" : "admin.healthy",
"user" : "healthy",
"db" : "admin",
"roles" : [
{
"role" : "dbOwner",
"db" : "helathy"
},
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
>
创建用户
docker exec -it mongodb mongo admin
> db.createUser({user:"healthy",pwd:"mongolive999",roles:[{role:"root",db:"admin"}]})
> use healthy
> db.createUser({user:"healthy",pwd:"mongolive999",roles:[{role:"dbOwner",db:"healthy"}]})
mongo的用户创建一定要切换到对应的库去操作。