MongoDB学习总结

初始

什么是MongoDB

MongoDB 是一个基于分布式文件存储的数据库。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

MongoDB学习总结_第1张图片

与MySQL相比的优势

1、弱一致性(最终一致),更能保证用户的访问速度
2、文档结构的存储方式,高扩展性

高扩展性,存储的数据格式是json格式

3、第三方支持丰富
4、性能优越

MySQL在海量数据处理的时候效率会显著变慢。

在适量级的内存的Mongodb的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快。

缺点

1、不支持事务操作
2、占用空间过大

安装下载

下载地址: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:显示数据库中有多少个集合

MongoDB学习总结_第2张图片


增删改查

数据库操作

创建数据库

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)

参数说明:

  • name: 要创建的集合名称
  • options: 可选参数, 指定有关内存大小及索引的选项
# 创建goods集合
> db.createCollection("goods")
{ "ok" : 1 }
  • 使用options

创建固定集合 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>
   }
)

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如 , , ,inc…)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。
# 例如:(将标题为“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>
   }
)

参数说明:

  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。
# 将所有name为“apple”的文档删除
db.goods.remove({name:"apple"})

# 如果你只想删除第一条找到的记录可以设置 justOne 为 1
db.goods.remove({name:"apple"},1)
  • 现在官方推荐使用 deleteOne() 和 deleteMany() 方法
# 删除goods集合下所有文档
db.goods.deleteMany({})

# 删除name等于apple的全部文档
db.goods.deleteMany({name:"apple"})

# 删除name等于zhangsan的一个文档
db.user.deleteOne({name:"zhangsan"})

查询

查询文档

db.collection.find(query, projection)
  • query :可选,使用查询操作符指定查询条件
  • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)
# 查询user集合中的所有文档
db.user.find()

# pretty()方法以格式化的方式来显示所有文档
db.col.find().pretty()
  • MongoDB 与 RDBMS Where 语句比较
操作 格式 范例 RDBMS中的类似语句
等于 {:} db.col.find({"by":"菜鸟教程"}).pretty() where by = '菜鸟教程'
小于 {:{$lt:}} db.col.find({"likes":{$lt:50}}).pretty() where likes < 50
小于或等于 {:{$lte:}} db.col.find({"likes":{$lte:50}}).pretty() where likes <= 50
大于 {:{$gt:}} db.col.find({"likes":{$gt:50}}).pretty() where likes > 50
大于或等于 {:{$gte:}} db.col.find({"likes":{$gte:50}}).pretty() where likes >= 50
不等于 {:{$ne:}} db.col.find({"likes":{$ne:50}}).pretty() where likes != 50
  • and条件

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件

db.col.find({key1:value1, key2:value2}).pretty()

db.goods.find({name:"computer",price:{$gte:6000}}).pretty()
  • or条件

MongoDB OR 条件语句使用了关键字 $or

查询键 by 值为 菜鸟教程 或键 title 值为 MongoDB 教程 的文档

db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
  • AND 和 OR 联合使用

以下实例演示了 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)

排序

  • 在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列
>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 }
  • skip(),limilt(),sort()三个放在一起执行的时候,执行的顺序是先 sort(),然后是 skip(),最后是显示的 limit()

聚合

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"}}}])


SpringBoot集成

环境配置


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
# 配置mongodb
spring.data.mongodb.uri=mongodb://localhost:27017/recruit

实战应用

文章模块

  • dao层

普通的增删改查方法可以直接调用mongoTemplate的默认方法,自定义方法则需在接口主动声明。

public interface ArticleRepository extends MongoRepository<Article, String> {

    /**
     * 根据模块名查找文章
     * @param moduleName
     * @return
     */
    List<Article> findByModuleName(String moduleName);

}
  • service层
@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安装

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")	# 测试

你可能感兴趣的:(数据库,mongodb,数据库)