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:123456@192.168.0.104: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

相关推荐
瓜牛_gn44 分钟前
mysql特性
数据库·mysql
奶糖趣多多2 小时前
Redis知识点
数据库·redis·缓存
CoderIsArt3 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
师太,答应老衲吧5 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Channing Lewis6 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
毕业设计制作和分享7 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil277 小时前
Redis - String 字符串
数据库·redis·缓存
Hsu_kk8 小时前
MySQL 批量删除海量数据的几种方法
数据库·mysql
编程学无止境8 小时前
第02章 MySQL环境搭建
数据库·mysql
knight-n8 小时前
MYSQL库的操作
数据库·mysql