MongoDB

1、SQL到MongoDB的映射图

SQL MongoDB
数据库(database) 数据库(database)
表(table) 集合(collection)
行row 文档(document)
列(column) 字段(field)
索引(index) 索引(index)
主键(primary key) _id(字段)
视图 (view) 视图 (view)
表连接(table joins) 聚合操作 ($lookup)

2、适合使用MongoDB的场景

  1. 应用不需要复杂/长事务及 join 支持
  2. 新应用,需求会变,数据模型无法确定,想快速迭代开发
  3. 应用需要2000-3000以上的读写QPS (更高也可以)
  4. 应用需要TB甚至 PB 级别数据存储
  5. 应用发展迅速,需要能快速水平扩展
  6. 应用要求存储的数据不丢失
  7. 应用需要99.999%高可用
  8. 应用需要大量的地理位置查询、文本查询

3、Linux安装

https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.26.tgz

命令1

进入bin目录,输入./mongo --help查看帮助信息

命令2

  1. 指定data和log路径

  2. 启动mongoDB

bash 复制代码
bin/mongod --port=27017 --dbpath=/app/mongodb-linux-x86_64-rhel70-4.4.26/data --logpath=/app/mongodb-linux-x86_64-rhel70-4.4.26/log/mongodb.log --bind_ip=0.0.0.0 --fork
  1. 进入bin目录打开mongoDB命令控制台

4、基础命令

  1. 查看所有数据库
bash 复制代码
show dbs
  1. 创建(切换)db

  2. 在控制台关闭mongoDB服务

bash 复制代码
db.shutdownServer()


菜鸟教程更多

https://www.runoob.com/mongodb/mongodb-tutorial.html

5、配置文件启动mongoDB

5.1、编辑编制文件

bash 复制代码
systemLog:
  destination: file
  path: /app/mongodb-linux-x86_64-rhel70-4.4.26/log/mongodb.log #指定日志输入文件夹(绝对路径)
  logAppend: true
storage:
  dbPath: /app/mongodb-linux-x86_64-rhel70-4.4.26/data #指定数据输入文件夹(绝对路径)
  engine: wiredTiger #存储引擎
  journal:
    enabled: true  #是否启动journal日志
net:
  bindIp: 0.0.0.0
  port: 27017
processManagement:
  fork: true

5.2、启动MongoDB

bash 复制代码
mongod -f /app/mongodb-linux-x86_64-rhel70-4.4.26/mongo.conf #启动配置文件绝对路径

进入bin目录输入./mongo打开命令控制台

5.3、关闭MongoDB

bash 复制代码
mongod -f /app/mongodb-linux-x86_64-rhel70-4.4.26/mongo.conf --shutdown ##配置文件绝对路径

6、Mongo shell



数据库操作

bash 复制代码
#查看所有数据库
show dbs
#use 切换数据库(创建)
use demodb
#删除当前数据库
db.dropDatabase()

集合操作

bash 复制代码
#查看所有集合
show collections
#创建集合
db.createCollection("studenttable")
#删除集合
db.studenttable.drop()

7、安全认证

7.1、创建管理员账号

bash 复制代码
#设置管理员用户密码需要在admin库
use admin
#创建管理员
db.createUser({user:"zmc",pwd:"123456",roles:["root"]})
#查看所有用户信息
show users
#删除用户
db.dropUser("zmc")
#验证用户
db.auth("zmc","123456")
权限名 描述
read 允许用户读取指定数据库
readWrite 允许用户读写指定数据库
dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
dbowner 允许用户在指定数据库中执行任意操作,增、删、改、查等
userAdmin 允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户
clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnvDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
root 只在admin数据库中可用。超级账号,超级权限

7.2、授权方式启动

  1. 加上--auth启动mongodb
bash 复制代码
mongod -f /app/mongodb-linux-x86_64-rhel70-4.4.26/mongo.conf --auth
  1. 使用有权限的账号密码认证
bash 复制代码
mongo -uzmc -p123456 --authenticationDatabase=admin

8、MongoDB文档操作

8.1、新增文档

新增单个文档

  • db.collection.insertOne()支持writeConcern
bash 复制代码
db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

writeConcern 决定一个写操作落到多少个节点上才算成功。writeConcern 的取值包括

0:发起写操作,不关心是否成功;

1:集群最大数据节点数: 写操作需要被复制到指定节点数才算成功

majority: 写操作需要被复制到大多数节点上才算成功。

bash 复制代码
db.student_info.insertOne({name:"小明",age:41,sex:"男"})
  • insert: 若插入的数据主键已经存在,则会抛 DuplicateKeyException 异常,提示主键重复,不保存当前数据.
bash 复制代码
db.student_info.insert({name:"李四",age:20,sex:"男"})

新增多个文档

  • insertMany()新增多个
bash 复制代码
db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)

writeConcern: 写入策略,默认为 1,即要求确认写操作,0 是不要求

ordered:指定是否按顺序写入,默认 true,按顺序写入

insert和save也可以实现批量插入

bash 复制代码
db.student_info.insertMany([{name:"王五",age:21,sex:"女"},{name:"赵六",age:23,sex:"女"}])
  • save:如果 id 主键存在则更新数据,如果不存在就插入数据。

8.2、练习测试

  • 创建js文件
javascript 复制代码
let tags=["nosql","MongoDB","document","developer","popular"];
let types =["technology","sociality","travel","novel","literature"];
var books=[];
for(let i=0;i<60;i++){
	let tagIndx=Math.floor(Math.random()*tags.length);
	let tyIndx=Math.floor(Math.random()*types.length);
	let favCount=Math.floor(Math.random()*120);
	let book={
		title:"book_"+(i+1),
		type:types[tyIndx],
		tag:tags[tagIndx],
		favCount:favCount,
		author:"zmc_"+(i+1)
	};
	books.push(book);
}
db.books.insertMany(books);
  • 载入数据库
bash 复制代码
load("/app/mongodb-linux-x86_64-rhel70-4.4.26/js/book.js") #js文件的绝对路径

8.3、查询文档

find

bash 复制代码
db.collection.find(query,projection)

query :可选,使用查询操作符指定查询条件相当于sql中的where
projection:可选,使用投影操作符指定返回的键(相当于返回sql表中指定的字段)。查询时返回文档中所有键值,只需省略该参数即可(默认省略)。投影时,id为1的时候,其他字段必须是1 ; id是0的时候,其他字段可以是0;如果没有_id字段约束,多个其他字段必须同为0或同为1。

例题

  • 查询title是book_2的数据
bash 复制代码
db.books.find({title:"book_2"})
  • 查询title是book_1并且author是author的数据
bash 复制代码
db.books.find({title:"book_1",author:"zmc_1"})
  • 查询type是"travel",tag是"document",但是只想返回title,type,tag三个字段
bash 复制代码
db.books.find({type:"travel",tag:"document"},{title:1,type:1,tag:1})

findOne

同find一样,但是findOne只返回第一条数据

bash 复制代码
db.collection.findOne(query,projection)
bash 复制代码
db.books.findOne({type:"travel",tag:"document"},{title:1,type:1,tag:1})

sql与mongodb查询条件对照表

SQL MongoDB
filed=1 {field:1}
filed<>1 {field:{$ne:1}}
filed>1 {field:{$gt:1}}
filed>=1 {field:{$gte:1}}
filed<1 {field:{$lt:1}}
filed<=1 {field:{$lte:1}}
filed1=1 AND filed2=3 {field1:1, filed2:3}或{$and:[{field1:1},{field2:3}]}
filed1=1 OR filed2=3 {$or:[{field1:1},{field2:3}]}
filed IS NULL {field:{$exists:false}}
filed IN (1,2,3) {field:{$in:[1,2,3]}}
filed NOT IN (1,2,3) {field:{$nin:[1,2,3]}}

例:

  • 1
bash 复制代码
#tag!=nosql 并且 type!=technology
db.books.find({tag:{$ne:"nosql"},type:{$ne:"technology"}})
  • 2
bash 复制代码
#favCount>99
db.books.find({favCount:{$gt:99}})
  • 3
bash 复制代码
#type=sociality 或者 tag=MongoDB
db.books.find({$or:[{type:"sociality"},{tag:"MongoDB"}]})
  • 4
bash 复制代码
#查询不存在author字段的数据,如果author=null或author=""则查不到
db.books.find({author:{$exists:false}})
  • 5
bash 复制代码
#tag IN ('nosql','popular','MongoDB',)
db.books.find({tag:{$in:["nosql","popular","MongoDB"]}})

排序

bash 复制代码
#查询type=sociality或者tagMongoDB,再根据type正序排序favCount倒序排序
db.books.find({$or:[{type:"sociality"},{tag:"MongoDB"}]}).sort({type:1,favCount:-1})

分页

bash 复制代码
#查询favCount>=60,再跳过前三条数据,限制为5条数据
db.books.find({favCount:{$gte:60}}).skip(3).limit(5)

正则匹配(模糊)查询

bash 复制代码
#type包含ve,相当于sql的type like '%ve%' 
db.books.find({type:{$regex:"ve"}})

也可以这样写

bash 复制代码
db.books.find({type:/ve/})

8.4、更新文档

bash 复制代码
db.collection.update(query,update,options)
  • query:描述更新的查询条件;相当于sql的where条件
  • update:描述更新的动作及新的内容;相当于sql的set
  • options:描述更新的选项
    • upsert:可选, 如果不存在update的记录,是否插入新的记录。默认false,不插入
    • multi:可选,是否更新多条记录。默认false,只更新找到的第一条记录
    • writeConcern :可选,决定一个写操作落到多少个节点上才算成功。

更新操作符

操作符 格式 描述
$set {$set:{field:value}} 指定一个键并更新值,若键不存在则创建
$unset {$unset:{field:1}} 删除一个键
$inc {$inc : {field : value } } 对数值类型进行增减
$rename {$rename :{old_field_name :new_field_name } } 修改字段名称
$push { $push : {field : value } } 将数值追加到数组中,若数组不存在则会进行初始化
$pushAll {$pushAll : {field : value_array}} 追加多个值到一个数组字段内
$pull {$pull : {field : _value } } 从数组中删除指定的元素
$addToSet {$addToSet : {field : value } } 添加元素到数组中,具有排重功能
$pop {$pop : {field : 1 }} 删除数组的第一个或最后一个元素

更新单个文档update

bash 复制代码
#把type=travel的数据,favCount减去100
db.books.update({type:"travel"},{$inc:{favCount:-100}})


更新单个文档updateOne

bash 复制代码
db.books.updateOne({type:"travel"},{$set:{createDate:"2133-12-23T11:48:22.913Z"}})

替换单个文档replaceOne

bash 复制代码
db.books.replaceOne({type:"travel"},{"title" : "book_116", "type" : "travel", "tag" : "developer", "favCount" : 81, "author" : "zmc_6", "createDate" : ISODate("2023-12-23T11:48:22.913Z")})

不使用操作符实现替换文档

不可实现替换多个文档

bash 复制代码
#彻底替换整个文档
db.books.update({type:"zmc"},{oneField:12222})

更新多个文档update

需要配合使用multi,设置为true

bash 复制代码
#更新多行数据,并添加createDate字段(如果没有该字段,则新增该字段)
db.books.update({type:"travel"},{$set:{createDate:new Date()}},{multi:true})

更新多个文档updateMany

bash 复制代码
db.books.updateMany({type:"travel"},{$set:{createDate:new Date()}})

不存在则插入upsert

bash 复制代码
db.books.update({type:"zmc"},{$set:{createDate:"2133-12-23T11:48:22.913Z",tag:[1,2,3]}},{upsert:true})

查询和修改单个文档findAndModify

findAndModify只能更新单个文档

  • 先查询旧值再更新文档
bash 复制代码
#先查询title=book_1的数据,再把该条数据的athor修改为zhangmengchao
db.books.findAndModify({query:{title:"book_1"},update:{$set:{author:"zhangmengchao"}}})
  • 先更新文档再查询修改后的内容
    加上参数new,设置为true
bash 复制代码
db.books.findAndModify({query:{title:"book_2"},update:{$set:{author:"zhangmengchao2"}},new:true})

与findAndModify语义相近的命令如下:

findOneAndUpdate:更新单个文档并返回史新前(或更新后)的文档。. findOneAndReplace:替换单个文档并返回替换前(或替换后的文档。

8.5、删除文档

删除多个文档remove

bash 复制代码
#删除type是sociality和novel并且favCount>=18的数据
db.books.remove({type:{$in:["sociality","novel"]},favCount:{$gte:18}})

满足条件的有17个全删了

删除单个文档remove

bash 复制代码
#justOne为true,代表只删除一个文档
db.books.remove({type:"travel"},{justOne:true})

删除所有文档remove

bash 复制代码
db.books.remove({})

删除单个文档deleteOne

bash 复制代码
#删除type=novel或者tag为MongoDB,并且favCount>100的一条数据
db.books.deleteOne({$or:[{type:"novel"},{tag:{$in:["MongoDB"]}}],favCount:{$gt:100}})

删除多个文档deleteMany

bash 复制代码
#删除type=novel或者tag为MongoDB,并且favCount>100的多条数据
db.books.deleteMany({$or:[{type:"novel"},{tag:{$in:["MongoDB"]}}],favCount:{$gt:100}})

删除所有文档

bash 复制代码
db.books.deleteMany({})

查询和删除单个文档findOneAndDelete

  • 删除文档后并返回删的文档
bash 复制代码
#删除author=zhangmengchao的文档
db.books.findOneAndDelete({"author" : "zhangmengchao"})
  • 先排序再删除文档
bash 复制代码
#查询出满足tag=popular的所有文档,再倒序排序。删除第一个文档
db.books.findOneAndDelete({"tag" : "popular"},{sort:{favCount:-1}})

remove、deleteOne等命令只能按默认顺序删除,利用这个特性, findOneAndDelete可以实现队列的先进先出。

9、MongoDB Compass (GUI)

https://downloads.mongodb.com/compass/mongodb-compass-1.41.0-win32-x64.exe

在Linux环境部署MongoDB需要开放MongoDB的端口

进入后的画面

10、整合SpringBoot

10.1、环境配置

xml 复制代码
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
yaml 复制代码
spring:
  data:
    mongodb:
      database: zmcdb
      host: 192.168.0.104
      port: 27017
      username: zmc
      password: '123456'   #注意密码加单引号
      authentication-database: admin
      #或者
#     uri: mongodb://zmc:[email protected]:27017/zmcdb?authSource=admin

10.2、注入MongoTemplate

java 复制代码
@Autowired
private MongoTemplate mongoTemplate;

10.3、 集合操作

java 复制代码
    /**
     * 判断集合(表)是否存在,删除集合(表),创建集合(表)
     */
    @Test
    public void createCollections() {
        final String COLLECTION_NAME = "student_info";
        boolean exists = mongoTemplate.collectionExists(COLLECTION_NAME);
        if (exists) {
            mongoTemplate.dropCollection(COLLECTION_NAME);
        }
        mongoTemplate.createCollection(COLLECTION_NAME);
    }

10.4、相关注解

@Document

  • 修饰范围:用在类上
  • 作用:用来映射这个类的一个对象为mongo中一条文栏数据。
  • 属性:( value 、collection )用来指定操作的集合名称

@MongoId

  • 修饰范围:用在成员变量、方法上
  • 作用:用来将成员变量的值映射为文档的id的值

@Field

  • 修饰范围:用在成员变量、方法上
  • 作用:用来将成员变量及其值映射为文档中一个key:value对。
  • 属性:( name , value )用来指定在文档中key的名称,默认为成员变量名

@Transient

  • 修饰范围:用在成员变量、方法上
  • 作用:用来指定此成员变量不参与文档的序列化
java 复制代码
@Document("student_info")
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class StudentInfoDTO {
    @MongoId
    private Integer id;
    @Field("stuName")//自定义文档的字段名
    private String name;
    @Field
    private Integer age;
    @Field
    private Character sex;
    @Field
    private Date birthday;

}

10.5、新增文档

新增单个文档insert

id不能重复,如果重复就会抛出异常

java 复制代码
@Test
    public void insertSingle() {
        StudentInfoDTO dto=new StudentInfoDTO(1,"张三",23,'男',new Date());
        StudentInfoDTO insert = mongoTemplate.insert(dto);
    }

相同id再次新增就会报错

新增多个文档insert

java 复制代码
    @Test
    public void insertMore() {
        List<StudentInfoDTO> listDto=new ArrayList<>(3);
        StudentInfoDTO dto1=new StudentInfoDTO(2,"小明",2,'男',new Date());
        StudentInfoDTO dto2=new StudentInfoDTO(3,"小黑",21,'女',new Date());
        StudentInfoDTO dto3=new StudentInfoDTO(4,"小白",20,'男',new Date());
        listDto.add(dto1);
        listDto.add(dto2);
        listDto.add(dto3);
        Collection<StudentInfoDTO> insert = mongoTemplate.insert(listDto, StudentInfoDTO.class);
    }

新增单个文档save

若id存在,则修改该文档

java 复制代码
@Test
    public void saveSingle() {
        StudentInfoDTO dto=new StudentInfoDTO(1,"老六",213,'男',new Date());
        StudentInfoDTO save = mongoTemplate.save(dto);
    }

10.6、查询文档

Criteria是标准查询的接口,可以引用静态的Criteria.where的把多个条件组合在起,就可以轻松地将多个方法标准和查询连接起来,方便我们操作查询语句。

Criteria、MongoDB、SQL对比

Criteria MongoDB SQL
Criteria and (String key) $and where field1=1 and field2=2
Criteria andOperator(Criteria... criteria) $and where field1=1 and field2=2
Criteria orOperator (Criteria. ... criteria) $or where field1=1 or field2=2
Criteria gt (Object o) $gt where field>1
Criteria gte (Object o) $gte where field>=1
Criteria in (Object... o) $in where field in (1,2,3)
Criteria is (Object o) $is where field =1
Criteria It(Object o) $lt where field<1
Criteria Ite (Object o) $lte where field<=1
Criteria nin (Object... o) $nin where field not in (1,2,3)

查询所有文档findAll

java 复制代码
    @Test
    public void criteriaFind() {
        //查询age>20 and stuName in ('老六','小黑')
        Query query = new Query(Criteria.where("age").gt(20).and("stuName").in("老六", "小黑"));
        List<StudentInfoDTO> dtoList = mongoTemplate.find(query, StudentInfoDTO.class);
        dtoList.forEach(System.out::println);
    }

根据id查询文档findById

java 复制代码
    @Test
    public void findById() {
        StudentInfoDTO byId = mongoTemplate.findById(1, StudentInfoDTO.class);
        System.out.println(byId);
    }

查询单个文档findOne

java 复制代码
    @Test
    public void findOne() {
        StudentInfoDTO one = mongoTemplate.findOne(new Query(), StudentInfoDTO.class);
        System.out.println(one);
    }

查询所有满足条件的文档

> and in
java 复制代码
    @Test
    public void criteriaFind() {
        //查询age>20
        Query query = new Query(Criteria.where("age").gt(20));
        List<StudentInfoDTO> dtoList = mongoTemplate.find(query, StudentInfoDTO.class);
        dtoList.forEach(System.out::println);
    }
> or and =
java 复制代码
    @Test
    public void criteriaFind2() {
        //查询age>30 or stuName = '小白' and sex='男'
        Criteria criteria = new Criteria().orOperator(
                Criteria.where("age").gt(30),
                Criteria.where("stuName").is("小白")
        ).andOperator(
                Criteria.where("sex").is("男")
        );
        Query query = new Query(criteria);
        List<StudentInfoDTO> studentInfoDTOS = mongoTemplate.find(query, StudentInfoDTO.class);
        studentInfoDTOS.forEach(System.out::println);
    }
like
java 复制代码
    @Test
    public void criteriaFind3() {
        //查询stuName like '%小%'
        Criteria criteria = Criteria.where("stuName").regex("小");
        Query query = new Query(criteria);
        List<StudentInfoDTO> studentInfoDTOS = mongoTemplate.find(query, StudentInfoDTO.class);
        studentInfoDTOS.forEach(System.out::println);
    }
order by 排序
java 复制代码
    @Test
    public void criteriaFind4() {
        //查询sex='男' order by age desc
        Criteria criteria = new Criteria();
        criteria.andOperator(Criteria.where("sex").is("男"));
        Query query = new Query(criteria);
        query.with(Sort.by(Sort.Order.desc("age")));
        List<StudentInfoDTO> studentInfoDTOS = mongoTemplate.find(query, StudentInfoDTO.class);
        studentInfoDTOS.forEach(System.out::println);
    }
skip limit分页
java 复制代码
    @Test
    public void criteriaFind5() {
        //where birthday<=当前时间 limit 1,3
        Criteria criteria = new Criteria();
        criteria.andOperator(Criteria.where("birthday").lte(new Date()));
        Query query = new Query(criteria);
        query.skip(1).limit(3);
        List<StudentInfoDTO> studentInfoDTOS = mongoTemplate.find(query, StudentInfoDTO.class);
        studentInfoDTOS.forEach(System.out::println);
    }

查询单个满足条件的文档

java 复制代码
    @Test
    public void criteriaFindOne() {
        //查询age>20 and stuName not in ('老六')
        Query query = new Query(Criteria.where("age").gte(20).and("stuName").nin("老六"));
        StudentInfoDTO one = mongoTemplate.findOne(query, StudentInfoDTO.class);
        System.out.println(one);
    }

JSON串查询

json查询不能分页和排序

java 复制代码
    @Test
    public void criteriaFind6() {
        //where age>=20 and stuName like '%小%'
        String json = "{age:{$gte:20},stuName:{$regex:\"小\"}})";
        Query query = new BasicQuery(json);
        query.with(Sort.by(Sort.Order.asc("age")));
        List<StudentInfoDTO> studentInfoDTOS = mongoTemplate.find(query, StudentInfoDTO.class);
        studentInfoDTOS.forEach(System.out::println);
    }

10.7、更新文档

更新第一条记录updateFirst

更新前的数据

更新后的数据

java 复制代码
    @Test
    public void updateFirst() {
        //update table set age+10 where age > 100 or stuName in ('小明','大明')
        Criteria criteria = new Criteria();
        criteria.orOperator(Criteria.where("age").gt(100),Criteria.where("stuName").in("小明", "大明"));
        Query query = new Query(criteria);
        Update update = new Update();
        update.inc("age",10);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, StudentInfoDTO.class);
        System.out.println(updateResult);
    }

更新所有满足条件的记录updateMulti

更新前的数据

更新后的数据

java 复制代码
    @Test
    public void updateMulti() {
        //update table set age=18 where sex='女'
        Query query = new Query(Criteria.where("sex").is("女"));
        Update update = new Update();
        update.set("age", 18);
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, StudentInfoDTO.class);
        System.out.println(updateResult);
    }

没有符合更新条件的则新增upsert

更新前的数据

更新后的数据

java 复制代码
    @Test
    public void upsert(){
        //update table set stuName="zmc",age=500,sex='男',salary=999999 where id=666
        Query query = new Query(Criteria.where("id").is(666));
        Update update = new Update();
        update.set("stuName","zmc")
                .set("age",500)
                .set("salary",999999);
        UpdateResult upsert = mongoTemplate.upsert(query, update, StudentInfoDTO.class);
        System.out.println(upsert);
    }

10.8、删除文档remove

删除前的数据

删除后的数据

java 复制代码
    @Test
    public void remove() {
        //delete from table where salary>100 or stuName='中白'
        Criteria criteria = new Criteria();
        criteria.orOperator(Criteria.where("salary").gt(100),Criteria.where("stuName").is("中白"));
        Query query = new Query(criteria);
        DeleteResult remove = mongoTemplate.remove(query, StudentInfoDTO.class);
        System.out.println(remove);
    }

11、聚合操作

如统计,求平均值,求和等。

聚合操作分为:单---作用聚合、聚合管道、MapReduce

  • 单一作用聚合:提供了对常见聚合过程的简单访问,操作都从单个集合聚合文档。
  • 聚合管道:类似Stream流
  • MapReduce操作具有两个阶段:处理每个文档并向每个输入文档发射一个或多个对象的map阶段,以及reduce组合map操作的输出阶段。

11.1、单一聚合操作

count

java 复制代码
#统计type=novel或者tag=MongoDB的数量
db.books.count({$or:[{"type" : "novel"},{"tag" : "MongoDB"}]})

estimatedDocumentCount

该命令会忽略查询条件

java 复制代码
db.books.estimatedDocumentCount({$or:[{"type" : "novel"},{"tag" : "MongoDB"}]})

distinct

java 复制代码
db.books.distinct("type",{$or:[{"type" : "novel"},{"tag" : "MongoDB"}]})

11.2、聚合管道类似Stream流

语法

bash 复制代码
pipeline = [$stage1,$stage2,$stage3...]
db.collection.aggregate(pipeline ,{options})
  • pipelines一组数据聚合阶段。除 o u t 、 out、 out、Merge和$geonear阶段之外,每个阶段都可以在管道中出现多次
  • options可选,聚合操作的其他参数。包含:查询计划、是否使用临时文件、游标、最大操作时间、读写策略、强制索引等等

常用操作

官方文档

https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/

数据准备

javascript 复制代码
let tags=["nosql","MongoDB","document","developer","popular"];
let types =["technology","sociality","travel","novel","literature"];
var books=[];
for(let i=0;i<60;i++){
	let tagIndx=Math.floor(Math.random()*tags.length);
	let tagIndx2=Math.floor(Math.random()*tags.length);
	let tyIndx=Math.floor(Math.random()*types.length);
	let favCount=Math.floor(Math.random()*120);
	let username="zmc"+Math.floor(Math.random()*10);
	let age=20+Math.floor(Math.random()*16);
	let book={
		title:"book_"+(i+1),
		type:types[tyIndx],
		tag:[tags[tagIndx],tags[tagIndx2]],
		favCount:favCount,
		author:{name:username,age:age}
	};
	books.push(book);
}
// console.log(books)
db.books2.insertMany(books);
bash 复制代码
#载入数据
load("/app/mongodb-linux-x86_64-rhel70-4.4.26/js/books2.js")

查看载入的数据

bash 复制代码
#pretty是格式化json数据
db.books2.find().pretty()

$project 设置别名,控制需要展示的字段

  • 设置别名
bash 复制代码
#把title改为bookName
db.books2.aggregate([{$project:{bookName:"$title"}}])
  • 控制需要展示的字段
bash 复制代码
#把title改为bookName,不展示id,展示type,technology,tag
db.books2.aggregate([{$project:{bookName:"$title",_id:0,type:1,technology:1,tag:1}}])

TODO

相关推荐
技术宝哥31 分钟前
Redis(2):Redis + Lua为什么可以实现原子性
数据库·redis·lua
学地理的小胖砸2 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
dddaidai1232 小时前
Redis解析
数据库·redis·缓存
数据库幼崽2 小时前
MySQL 8.0 OCP 1Z0-908 121-130题
数据库·mysql·ocp
Amctwd3 小时前
【SQL】如何在 SQL 中统计结构化字符串的特征频率
数据库·sql
betazhou3 小时前
基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL
linux·数据库·mysql·oracle·ogg
lyrhhhhhhhh4 小时前
Spring 框架 JDBC 模板技术详解
java·数据库·spring
喝醉的小喵5 小时前
【mysql】并发 Insert 的死锁问题 第二弹
数据库·后端·mysql·死锁
付出不多5 小时前
Linux——mysql主从复制与读写分离
数据库·mysql
初次见面我叫泰隆5 小时前
MySQL——1、数据库基础
数据库·adb