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的场景
- 应用不需要复杂/长事务及 join 支持
- 新应用,需求会变,数据模型无法确定,想快速迭代开发
- 应用需要2000-3000以上的读写QPS (更高也可以)
- 应用需要TB甚至 PB 级别数据存储
- 应用发展迅速,需要能快速水平扩展
- 应用要求存储的数据不丢失
- 应用需要99.999%高可用
- 应用需要大量的地理位置查询、文本查询
3、Linux安装
https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.26.tgz
命令1
进入bin目录,输入./mongo --help
查看帮助信息
命令2
-
指定data和log路径
-
启动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
- 进入bin目录打开mongoDB命令控制台
4、基础命令
- 查看所有数据库
bash
show dbs
-
创建(切换)db
-
在控制台关闭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、授权方式启动
- 加上
--auth
启动mongodb
bash
mongod -f /app/mongodb-linux-x86_64-rhel70-4.4.26/mongo.conf --auth
- 使用有权限的账号密码认证
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}}])