MangoDB增删改查

MangoDB简介

    • 数据模型
    • MongoDB的特点
    • 基本常用命令
    • 数据库操作
      • 选择和创建数据库
      • 数据库的删除
      • 集合操作
        • 集合的显示创建
        • 集合的删除
      • 文档基本crud
        • 文档的插入
      • 常用命令总结
    • SpringBoot集成MangoDB
      • 环境搭建
      • 文章评论实体类
      • 文章评论的基本增删改查

​ MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最 像关系型数据库(MySQL)的非关系型数据库。 它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。 MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认 为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。

MangoDB增删改查_第1张图片

SQL术语 MangoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
tables joins 表连接,MangoDB不支持
嵌入文档 MangoDB通过嵌入式文档来代替多表连接
primary key primary key 主键,MangoDB自动将_id字段设置为主键

数据模型

MongoDB的最小存储单位就是文档(document)对象。

文档(document)对象对应于关系型数据库的行。

数据在MongoDB中以 BSON(Binary-JSON)文档的格式存储在磁盘上。 BSON(Binary Serialized Document Format)是一种类json的一种二进制形式的存储格式,简称Binary JSON。BSON和JSON一样,支持 内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。 BSON采用了类似于 C 语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具有轻量性、可遍历性、高效性的三个特点,可 以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高,但它的缺点是空间利用率不是很理想。 Bson中,除了基本的JSON类型:string,integer,boolean,double,null,array和object,mongo还使用了特殊的数据类型。这些类型包括 date,object id,binary data,regular expression 和code。每一个驱动都以特定语言的方式实现了这些类型,查看你的驱动的文档来获取详 细信息。

BSON数据类型参考列表:

数据类型 描述 举例
字符串 UTF-8字符串都可表示为字符串类型的数据 {“x” : “foobar”}
对象id 对象id是文档的12字节的唯一 ID “X” :ObjectId() }
布尔值 真或者假:true或者false {“x”:true}+
数组 值的集合或者列表可以表示成数组 {“x” : [“a”, “b”, “c”]}
32位整数 类型不可用。JavaScript仅支持64位浮点数,所以32位整数会被 自动转换。 shell是不支持该类型的,shell中默认会转换成64 位浮点数
64位整数 不支持这个类型。shell会使用一个特殊的内嵌文档来显示64位 整数 shell是不支持该类型的,shell中默认会转换成64 位浮点数
64位浮点数 shell中的数字就是这一种类型 {“x”:3.14159,“y”:3}
null 表示空值或者未定义的对象 {“x”:null}
undefined 文档中也可以使用未定义类型 {“x”:undefined}
符号 shell不支持,shell会将数据库中的符号类型的数据自动转换成 字符串
正则表达式 文档中可以包含正则表达式,采用JavaScript的正则表达式语法 {“x” : /foobar/i}
代码 文档中还可以包含JavaScript代码 {“x” : function() { /* …… */ }}
二进制数据 二进制数据可以由任意字节的串组成,不过shell中无法使用
最大值/最小值 BSON包括一个特殊类型,表示可能的最大值。shell中没有这个 类型。

提示: shell默认使用64位浮点型数值。{“x”:3.14}或{“x”:3}。对于整型值,可以使用NumberInt(4字节符号整数)或NumberLong(8字节符 号整数),{“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}

MongoDB的特点

MongoDB主要有如下特点:

  1. 高性能: MongoDB提供高性能的数据持久性。特别是, 对嵌入式数据模型的支持减少了数据库系统上的I/O活动。 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地 理位置索引可用于构建各种 O2O 应用) mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求。 Gridfs解决文件存储的需求。
  2. 高可用性: MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。
  3. 高扩展性: MongoDB提供了水平可扩展性作为其核心功能的一部分。 分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展) 从3.4开始,MongoDB支持基于片键创建数据区域。在一个平衡的集群中,MongoDB将一个区域所覆盖的读写只定向到该区域内的那些 片。
  4. 丰富的查询支持: MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。
  5. 其他特点:如无模式(动态模式)、灵活的文档模型、

基本常用命令

存放文章评论的数据存放到MangoDB中,数据结构参考

数据库:articledb

专栏文章评论 comment
字段名称 字段含义 字段类型 备注
_id ID Object或String MangoDB的主键的字段
articleid 文章ID String
content 评论内容 String
userid 评论人ID String
nickname 评论人昵称 String
createdatetime 评论的日期时间 Date
likenum 点赞数 int32
replynum 回复数 int32
state 状态 String 0:不可见;1:可见
parentid 上级ID String 如果为0表示文章的顶级评论

数据库操作

选择和创建数据库

选择和创建数据库的语法格式

use 数据库名称

如果数据库不存在则自动创建

use artcledb

查看有权限产看的所有的数据库命令

show dbs
show databases

查看当前正在使用数据库的命令

db

MongoDB 中默认的数据库为 test,如果你没有选择数据库,集合将存放在 test 数据库中。

  • 另外: 数据库名可以是满足以下条件的任意UTF-8字符串。
  • 不能是空字符串(“”)。
  • 不得含有’ '(空格)、.、$、/、\和\0 (空字符)。
  • 应全部小写。
  • 最多64字节。

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

  • admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特 定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

数据库的删除

mangoDB删除数据的语法格式如下

db.dropDatabase()

提示:主要用来删除已经持久化的数据库

集合操作

集合,类似关系型数据中的表

可以显示的创建,也可以隐式的创建

集合的显示创建

db.createCollection(name)

参数说明:

  • name:要创建的集合名称

创建一个名为mycollection的普通集合

db.createCollection("mycollection")

查看当前库中的表:show tables命令

show collections
或
show tables

集合的命名规范:

  • 集合名不能是空字符串""。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以"system."开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除 非你要访问这种系统创建的集合,否则千万不要在名字里出现$。

集合的删除

语法如下

db.collection.drop()
或
db.集合.drop()

返回值

如果成功删除选定集合,则drop方法返回true,否则返回false

例如删除mycollection集合
db.mycollection.drop()

文档基本crud

文档(document)的数据结构和 JSON 基本一样。 所有存储在集合中的数据都是 BSON 格式。

文档的插入

  • 单个文档插入

​ 使用insert() 或 save() 方法向集合中插入文档,语法如下:

db.collection.insert(
    ,
    {
        writeConcern: ,
        ordered: 
    }
)

参数:

Parameter Type Description
document document or array 要插入到集合中的文档或文档数组。((json格式)
writeConcern document
ordered boolean 可选。如果为真,则按顺序插入数组中的文档,如果其中一个文档出现错误,MongoDB将返回而 不处理数组中的其余文档。如果为假,则执行无序插入,如果其中一个文档出现错误,则继续处理 数组中的主文档。在版本2.6+中默认为true

示例

要向comment的集合(表)中插入一条测试数据

db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明
媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null})

提示:

  • comment集合如果不存在,则会隐式创建
  • mango中的数字,默认情况下是double类型,如果要存整型,必须使用Numberint(整型数字),否则取出来有问题
  • 插入当前日期 使用 new Date()
  • 插入的数据没有指定_id,会自动生成主键值
  • 如果某字段没值,可以赋值为null,或不写字段

执行后,如下,说明插入一个数据成功了

writeResult({"nInerted":1})

注意:

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。 文档键命名规范: 键不能含有\0 (空字符)。这个字符用来表示键的结尾。 .和$有特别的意义,只有在特定环境下才能使用。 以下划线"_"开头的键是保留的(不是严格要求的)。
  • 批量插入

​ 语法

db.collection.insertMany(
    [  , , ... ],
    {
        writeConcern: ,
        ordered: 
    }
)

参数:

Parameter Type Description
document document 要插入到集合中的文档或文档数组。((json格式)
writeConcern document
ordered boolean 可选。一个布尔值,指定Mongod实例应执行有序插入还是无序插入。默认为true。

示例

批量插入多条文章评论

db.comment.insertMany([
{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我
他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-
05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},
{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔
悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},
{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船
长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},
{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯
撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},
{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫
嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-
06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}
]);

提示: 插入时指定了 _id ,则主键就是该值。 如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。 因为批量插入由于数据较多容易出现失败,因此,可以使用try catch进行异常捕捉处理,测试的时候可以不处理。如(了解):

try {
db.comment.insertMany([
{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我
他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-
05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},
{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔
悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},
{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船
长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},
{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯
撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},
{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫
嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-
06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}
]);
} catch (e) {
print (e);
}

文档的基本查询

查询数据的语法格式如下:

db.collection.find(, [projection])

参数:

参数 类型 说明
query document 可选,使用查询运算符指定选择筛选器,若要返回集合中的所有文档,请省略此参数或传递空文档({})。
projection document 可选,指定要在与查询筛选器匹配的文档中返回的字段(投影)。若要返回匹配文档中的所有字段, 请省略此参数。

示例

查询所有

如果我们要查询split集合的所有文档,我们输入以下命令

db.comment.find()
或
db.comment.find({})

这里你会发现每条文档会有一个叫_id的字段,这个相当于我们原来关系数据库中表的主键,当你在插入文档记录时没有指定该字段, MongoDB会自动创建,其类型是ObjectID类型。

如果我们在插入文档记录时指定该字段也可以,其类型可以是ObjectID类型,也可以是MongoDB支持的任意类型。

如果我想按一定条件来查询,比如我想查询userid为1003的记录,怎么办?很简单!只 要在find()中添加参数即可,参数也是json格式,如 下:

db.comment.find({userid:'1003'})

文档的更新

更新文档的语法

db.collection.update(query, update, options)
//或
db.collection.update(
,
,
{
upsert: ,
multi: ,
writeConcern: ,
collation: ,
arrayFilters: [ , ... ],
hint:  // Available starting in MongoDB 4.2
}
)

删除文档

删除文档的语法结构

db.集合名称.remove(条件)

以下语句可以将数据全部删除,请慎用

db.comment.remove({})

如果删除_id=1的记录,输入以下语句

db.comment.remove({_id:"1"})

常用命令总结

选择切换数据库:use articledb

插入数据:db.comment.insert({bson数据})

查询所有数据:db.comment.find();

条件查询数据:db.comment.find({条件})

查询符合条件的第一条记录:db.comment.findOne({条件})

查询符合条件的前几条记录:db.comment.find({条件}).limit(条数)

查询符合条件的跳过的记录:db.comment.find({条件}).skip(条数)

修改数据:db.comment.update({条件},{修改后的数据}) 或
db.comment.update({条件},{$set:{要修改部分的字段:数据})

修改数据并自增某字段值:db.comment.update({条件},{$inc:{自增的字段:步进值}})

删除数据:db.comment.remove({条件})

统计查询:db.comment.count({条件})

模糊查询:db.comment.find({字段名:/正则表达式/})

条件比较运算:db.comment.find({字段名:{$gt:值}})

包含查询:db.comment.find({字段名:{$in:[值1,值2]}})或
db.comment.find({字段名:{$nin:[值1,值2]}})

条件连接查询:db.comment.find({$and:[{条件1},{条件2}]})或
db.comment.find({$or:[{条件1},{条件2}]})

SpringBoot集成MangoDB

环境搭建

  1. 搭建项目工程模块

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
<relativePath/> 
parent>
    <groupId>com.liugroupId>
    <artifactId>articleartifactId>
    <version>1.0-SNAPSHOTversion>
<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starterartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-mongodbartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
    <dependency>
        <groupId>joda-timegroupId>
        <artifactId>joda-timeartifactId>
        <version>2.10.1version>
    dependency>

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintagegroupId>
                <artifactId>junit-vintage-engineartifactId>
            exclusion>
        exclusions>
    dependency>
dependencies>
project>
  1. 创建application.yml

    spring:
    #数据源配置
    	data:
    		mongodb:
                # 主机地址
                host: localhost
                # 数据库
                database: articledb
                # 默认端口是27017
                port: 27017
                #也可以使用uri连接
                #uri: mongodb://192.168.40.134:27017/articledb
    
  2. 创建启动类

    package com.liu.article;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    @SpringBootApplication
    public class ArticleApplication {
        public static void main(String[] args) {
            SpringApplication.run(ArticleApplication.class, args);
        }
    }
    
    

    4.启动项目

文章评论实体类

创建实体类 创建包com.liu.article,包下建包po用于存放实体类,创建实体类

cn.itcast.article.po.Comment

package cn.itcast.article.po;
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.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 文章评论实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Document(collection="comment")
public class Comment implements Serializable {
//主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
@Id
private String id;//主键
//该属性对应mongodb的字段的名字,如果一致,则无需该注解
@Field("content")
private String content;//吐槽内容
private Date publishtime;//发布日期
private String userid;//发布人ID
private String nickname;//昵称
private LocalDateTime createdatetime;//评论的日期时间
private Integer likenum;//点赞数
private Integer replynum;//回复数
private String state;//状态
private String parentid;//上级ID
private String articleid;
}

文章评论的基本增删改查

创建数据访问接口 com.liu.article包下创建dao包,

  1. 包下创建接口 com.liu.article.dao.CommentRepository
package com.liu.article.dao;
import com.liu.article.po.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
//评论的持久层接口
public interface CommentRepository extends MongoRepository<Comment,String> {
}
  1. 创建业务逻辑类 com.liu.article包下创建service包,

    包下创建类 com.liu.article.service.CommentService

package com.liu.article.service;
import com.liu.article.dao.CommentRepository;
import com.liu.article.po.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
//评论的业务层
@Service
public class CommentService {
    //注入dao
    @Autowired
    private CommentRepository commentRepository;
    /**
    * 保存一个评论
    * @param comment
    */
    public void saveComment(Comment comment){
        //如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
        //设置一些默认初始值。。。
        //调用dao
        commentRepository.save(comment);
    }
    /**
    * 更新评论
    * @param comment
    */
    public void updateComment(Comment comment){
        //调用dao
        commentRepository.save(comment);
    }
    /**
    * 根据id删除评论
    * @param id
    */
    public void deleteCommentById(String id){
        //调用dao
        commentRepository.deleteById(id);
    }
    /**
    * 查询所有评论
    * @return
    */
    public List<Comment> findCommentList(){
        //调用dao
        return commentRepository.findAll();
    }
    /**
    * 根据id查询评论
    * @param id
    * @return
    */
    public Comment findCommentById(String id){
    //调用dao
        return commentRepository.findById(id).get();
    }
}
  1. 新建Junit测试类,测试保存和查询所有:com.liu.article.service.CommentServiceTest
package com.liut.article.service;
import com.liu.article.ArticleApplication;
import com.liu.article.po.Comment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.LocalDateTime;
import java.util.List;
//测试评论的业务层
//SpringBoot的Junit集成测试
@RunWith(SpringRunner.class)
//SpringBoot的测试环境初始化,参数:启动类
@SpringBootTest(classes = ArticleApplication.class)
public class CommentServiceTest {
    //注入Service
    @Autowired
    private CommentService commentService;
    /**
    * 保存一个评论
    */
    @Test
    public void testSaveComment(){
        Comment comment=new Comment();
        comment.setArticleid("100000");
        comment.setContent("测试添加的数据");
        comment.setCreatedatetime(LocalDateTime.now());
        comment.setUserid("1003");
        comment.setNickname("凯撒大帝");
        comment.setState("1");
        comment.setLikenum(0);
        comment.setReplynum(0);
        commentService.saveComment(comment);
    }
    /**
    * 查询所有数据
    */
    @Test
    public void testFindAll(){
        List<Comment> list = commentService.findCommentList();
        System.out.println(list);
    }
    /**
    * 测试根据id查询
    */
    @Test
    public void testFindCommentById(){
        Comment comment = commentService.findCommentById("5d6a27b81b8d374798cf0b41");
        System.out.println(comment);
    }
}

你可能感兴趣的:(中间件,数据仓库,spring,boot)