MongoDB 是一个基于分布式文件存储的数据库。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
高扩展性,存储的数据格式是json格式
MySQL在海量数据处理的时候效率会显著变慢。
在适量级的内存的Mongodb的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快。
下载地址:https://www.mongodb.com/try/download/community
在data目录下创建db文件夹,在mongodb的bin目录下打开cmd输入命令 mongod -dbpath 所在位置
D:\Environment\MongoDB\bin>mongod -dbpath D:\Environment\MongoDB\data\db
1、cmd输入命令 net start mongodb
2、启动mongo.exe
show dbs :显示当前所有数据库
use 数据库 :进入到指定数据库(不管有没有该数据库,都可以进入,若插入了文档,便会创建该数据库)
db:当前所处数据库
show collections:显示数据库中有多少个集合
use DATABASE_NAME
# 如果数据库不存在,则创建数据库,否则切换到指定数据库
# 或者插入时创建数据库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> db.test.insert({"name":"Kim"})
WriteResult({ "nInserted" : 1 })
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
db.dropDatabase()
# 删除当前数据库,默认为 test,你可以使用 db 命令查看当前数据库名。
语法格式:
db.createCollection(name, options)
参数说明:
# 创建goods集合
> db.createCollection("goods")
{ "ok" : 1 }
创建固定集合 mycol
,整个集合空间大小 6142800 KB, 文档最大个数为 10000 个。
> db.createCollection("mycol", { capped : true, autoIndexId : true, size :
6142800, max : 10000 } )
{ "ok" : 1 }
>
在 MongoDB 中,你不需要创建集合。当你插入一些文档时,MongoDB 会自动创建集合。
> db.mycol2.insert({"name" : "菜鸟教程"})
> show collections
mycol2
...
db.collection.drop()
# 举例
> show collections
test
user
> db.test.drop()
true
> show collections
user
文档的数据结构和 JSON 基本一样。
所有存储在集合中的数据都是 BSON 格式。
BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
insert:插入一个或多个
插入一个
db.user.insert({name:"zhangsan",age:20})
插入多个(使用中括号[])
db.goods.insert([{name:"apple",price:5},{name:"computer",price:6999}])
insertOne:插入一个
> db.user.insertOne({name:"zhangsan",age:32})
{
"acknowledged" : true,
"insertedId" : ObjectId("6039dc6c9b01016868fc8027")
}
insertMany:插入多个
db.goods.insertMany([{name:"chair",price:49},{name:"computer",price:6999}])
>db.col.insert({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})
# update语句基本语法
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
参数说明:
# 例如:(将标题为“MongoDB 教程”改为“MongoDB”)
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
# 以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})
# 将goods集合中name为"apple"的修改为"food"(只修改第一条发现的文档)
> db.goods.find()
{ "_id" : ObjectId("5fcb0237be45c9df825a5558"), "name" : "apple", "price" : 5 }
{ "_id" : ObjectId("5fcb0317be45c9df825a5559"), "name" : "chair", "price" : 49 }
{ "_id" : ObjectId("5fcb0317be45c9df825a555a"), "name" : "computer", "price" : 6999 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555b"), "name" : "apple", "price" : 5 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555c"), "name" : "computer", "price" : 6999 }
> db.goods.update({name:"apple"},{$set:{name:"food"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.goods.find()
{ "_id" : ObjectId("5fcb0237be45c9df825a5558"), "name" : "food", "price" : 5 }
{ "_id" : ObjectId("5fcb0317be45c9df825a5559"), "name" : "chair", "price" : 49 }
{ "_id" : ObjectId("5fcb0317be45c9df825a555a"), "name" : "computer", "price" : 6999 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555b"), "name" : "apple", "price" : 5 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555c"), "name" : "computer", "price" : 6999 }
> db.goods.update({name:"apple"},{$set:{name:"food"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.goods.find()
{ "_id" : ObjectId("5fcb0237be45c9df825a5558"), "name" : "food", "price" : 5 }
{ "_id" : ObjectId("5fcb0317be45c9df825a5559"), "name" : "chair", "price" : 49 }
{ "_id" : ObjectId("5fcb0317be45c9df825a555a"), "name" : "computer", "price" : 6999 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555b"), "name" : "food", "price" : 5 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555c"), "name" : "computer", "price" : 6999 }
# 将goods集合中所有name为"food"的修改为"apple"(修改多条相同的文档,则需要设置 multi 参数为 true)
> db.goods.update({name:"food"},{$set:{name:"apple"}},{multi:true})
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
> db.goods.find()
{ "_id" : ObjectId("5fcb0237be45c9df825a5558"), "name" : "apple", "price" : 5 }
{ "_id" : ObjectId("5fcb0317be45c9df825a5559"), "name" : "chair", "price" : 49 }
{ "_id" : ObjectId("5fcb0317be45c9df825a555a"), "name" : "computer", "price" : 6999 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555b"), "name" : "apple", "price" : 5 }
{ "_id" : ObjectId("5fcb0346be45c9df825a555c"), "name" : "computer", "price" : 6999 }
# remove语句基本语法
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
# 将所有name为“apple”的文档删除
db.goods.remove({name:"apple"})
# 如果你只想删除第一条找到的记录可以设置 justOne 为 1
db.goods.remove({name:"apple"},1)
# 删除goods集合下所有文档
db.goods.deleteMany({})
# 删除name等于apple的全部文档
db.goods.deleteMany({name:"apple"})
# 删除name等于zhangsan的一个文档
db.user.deleteOne({name:"zhangsan"})
db.collection.find(query, projection)
# 查询user集合中的所有文档
db.user.find()
# pretty()方法以格式化的方式来显示所有文档
db.col.find().pretty()
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | { } |
db.col.find({"by":"菜鸟教程"}).pretty() |
where by = '菜鸟教程' |
小于 | { |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes < 50 |
小于或等于 | { |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes <= 50 |
大于 | { |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes > 50 |
大于或等于 | { |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes >= 50 |
不等于 | { |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes != 50 |
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件
db.col.find({key1:value1, key2:value2}).pretty()
db.goods.find({name:"computer",price:{$gte:6000}}).pretty()
MongoDB OR 条件语句使用了关键字 $or
查询键 by 值为 菜鸟教程 或键 title 值为 MongoDB 教程 的文档
db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: 'where likes>50 AND (by = ‘菜鸟教程’ OR title = ‘MongoDB 教程’)'
db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
db.goods.find({name:"computer",$or:[{price:{$gte:6000}},{price:4999}]}).pretty()
{
"_id" : ObjectId("6039dba49b01016868fc8026"),
"name" : "computer",
"price" : 6999
}
{
"_id" : ObjectId("603a00f19b01016868fc802b"),
"name" : "computer",
"price" : 4999
}
查询 title 包含"教"字的文档:
db.col.find({title:/教/})
查询 title 字段以"教"字开头的文档:
db.col.find({title:/^教/})
查询 titl e字段以"教"字结尾的文档:
db.col.find({title:/教$/})
# 返回指定NUMBER数量的数据记录
db.COLLECTION_NAME.find().limit(NUMBER)
>db.COLLECTION_NAME.find().sort({KEY:1})
# 按价格 升序 排序
> db.goods.find().sort({price:1})
{ "_id" : ObjectId("6039e2589b01016868fc8029"), "name" : "box" }
{ "_id" : ObjectId("603a00f19b01016868fc802a"), "name" : "chair", "price" : 90 }
{ "_id" : ObjectId("603a00f19b01016868fc802b"), "name" : "computer", "price" : 4999 }
{ "_id" : ObjectId("6039dba49b01016868fc8026"), "name" : "computer", "price" : 6999 }
MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。
有点类似 SQL 语句中的 count(*)
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
"result" : [
{
"_id" : "runoob.com",
"num_tutorial" : 2
},
{
"_id" : "Neo4j",
"num_tutorial" : 1
}
],
"ok" : 1
}
>
以上实例类似sql语句:
select by_user, count(*) from mycol group by by_user
在上面的例子中,我们通过字段 by_user 字段对数据进行分组,并计算 by_user 字段相同值的总和。
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { s u m : " sum : " sum:"likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { a v g : " avg : " avg:"likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m i n : " min : " min:"likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m a x : " max : " max:"likes"}}}]) |
$push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { p u s h : " push: " push:"url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { a d d T o S e t : " addToSet : " addToSet:"url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", first_url : { f i r s t : " first : " first:"url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", last_url : { l a s t : " last : " last:"url"}}}]) |
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
# 配置mongodb
spring.data.mongodb.uri=mongodb://localhost:27017/recruit
普通的增删改查方法可以直接调用mongoTemplate的默认方法,自定义方法则需在接口主动声明。
public interface ArticleRepository extends MongoRepository<Article, String> {
/**
* 根据模块名查找文章
* @param moduleName
* @return
*/
List<Article> findByModuleName(String moduleName);
}
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleRepository articleRepository;
@Autowired
private MongoTemplate mongoTemplate;
/**
* 获取默认文章(4个)
* @return
*/
@Override
public ResultInfo<List<Article>> findDefaultArticle() {
Query query = new Query();
Sort sort = Sort.by("gmtCreate").descending();
PageRequest pageRequest = PageRequest.of(0, 4);
query.with(sort);
query.with(pageRequest);
List<Article> articleList = mongoTemplate.find(query, Article.class);
return ResultInfo.success(CodeEnum.SUCCESS, articleList);
}
/**
* 根据模块名查找文章
* @param moduleName
* @return
*/
@Override
public ResultInfo<List<Article>> findByModuleName(String moduleName) {
List<Article> articles = articleRepository.findByModuleName(moduleName);
return ResultInfo.success(CodeEnum.SUCCESS, articles);
}
/**
* 根据文章标题模糊查询
* @param articleTitle
* @return
*/
@Override
public ResultInfo<List<Article>> findByArticleTitle(String articleTitle) {
Pattern pattern =
Pattern.compile("^.*" + articleTitle + ".*$", Pattern.CASE_INSENSITIVE);
Query query = new Query();
query.addCriteria(Criteria.where("articleTitle").regex(pattern));
Sort sort = Sort.by("gmtCreate").descending();
query.with(sort);
List<Article> articles = mongoTemplate.find(query, Article.class);
return ResultInfo.success(CodeEnum.SUCCESS, articles);
}
}
@Validated
@Service
public class QuestionServiceImpl implements QuestionService {
@Autowired
private QuestionRepository questionRepository;
@Autowired
private MongoTemplate mongoTemplate;
/**
* 新增一道题目
* @param question
*/
@Override
public void saveOne(Question question) {
questionRepository.save(question);
}
/**
* 自由模式随机查找一道题
* @return
*/
@Override
public ResultInfo<Question> getOneQuestion(){
List<Question> questions = new LinkedList<>();
// Aggregation.sample()可随机抽选指定数量的数据
TypedAggregation<Question> aggregation =
Aggregation.newAggregation(Question.class, Aggregation.sample(1));
AggregationResults<Question> results =
mongoTemplate.aggregate(aggregation, Question.class);
results.forEach(result->{
questions.add(result);
});
if(questions.isEmpty()){
return ResultInfo.error(CodeEnum.PARAM_NOT_IDEAL, null);
}else{
return ResultInfo.success(CodeEnum.SUCCESS, questions.get(0));
}
}
/**
* 自由模式根据模块名随机查找一道题
* @param moduleName
* @return
*/
@Override
public ResultInfo<Question> getOneQuestionByName(@NotBlank String moduleName){
List<Question> questions = new LinkedList<>();
MatchOperation match =
Aggregation.match(Criteria.where("moduleName").is(moduleName));
TypedAggregation<Question> aggregation =
Aggregation.newAggregation(Question.class, match, Aggregation.sample(1));
AggregationResults<Question> results =
mongoTemplate.aggregate(aggregation, Question.class);
results.forEach(result->{
questions.add(result);
});
if(questions.size() == 0){
return ResultInfo.error(CodeEnum.PARAM_NOT_IDEAL, null);
}else{
return ResultInfo.success(CodeEnum.SUCCESS, questions.get(0));
}
}
/**
* 闯关模式根据模块名随机查找10道题
* @param moduleName
* @return
*/
@Override
public ResultInfo<List<Question>> getQuestionsByName(@NotBlank String moduleName){
List<Question> questions = new LinkedList<>();
MatchOperation match =
Aggregation.match(Criteria.where("moduleName").is(moduleName));
TypedAggregation<Question> aggregation =
Aggregation.newAggregation(Question.class, match, Aggregation.sample(10));
AggregationResults<Question> results =
mongoTemplate.aggregate(aggregation, Question.class);
results.forEach(result->{
questions.add(result);
});
return ResultInfo.success(CodeEnum.SUCCESS, questions);
}
}
docker pull mongo:4.4.1
docker run -p 27017:27017 --name mongo -v /home/mongo/db:/data/db -d mongo:4.4.1 --auth
docker exec -it mongo mongo #进入容器
use admin
> db.createUser({
... user: "KimTou",
... pwd: "123456",
... roles: [{ role:"root",db:"admin" }] });
> db.auth("KimTou","123456") # 测试