一、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
二、自定义配置MongoTemplate
@Configuration
public class MongodbConfig {
@Value("${spring.data.mongodb.host}")
private String host;
@Value("${spring.data.mongodb.port}")
private int port;
@Value("${spring.data.mongodb.database}")
private String database;
@Bean
public MongoTemplate myCongoTemplate() {
ServerAddress serverAddress = new ServerAddress(host, port);
//用户名、密码 登录验证
// MongoCredential mongoCredential = MongoCredential.createCredential("username",
// "databaseName", "password".toCharArray());
// List<MongoCredential> credentials = new ArrayList<>();
// credentials.add(mongoCredential);
// MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
// MongoClientOptions mongoClientOptions = builder.build();
MongoClient mongoClient = new MongoClient(serverAddress);
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, database);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
return mongoTemplate;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
}
三、mongodb的增删改查以及聚合操作api
/**
* @Description: 集合实体类,
*/
@Document(collection = "DocumentEntity")
@Data
public class DocumentEntity {
/**id字段不要赋值, 插入后mongodb会自动生成唯一id, 查询时会自动设置到id字段上*/
private String id;
private String name;
private Integer age;
private String sex;
private Integer score;
/**@Indexed修饰的字段设置为索引,并且在date类型的索引下可以设置文档的过期时间*/
@Indexed(expireAfterSeconds = 120)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date dateTime;
}
@RestController
@RequestMapping("/mongodb")
@Slf4j
public class MongodbController {
@Autowired
private MongoTemplate myCongoTemplate;
@RequestMapping("/addData")
public DocumentEntity addData(@RequestBody DocumentEntity entity) {
//添加成功后结果数据,包含objectId
myCongoTemplate.insert(entity);
return entity;
}
@RequestMapping("/queryData")
public List<DocumentEntity> queryData(@RequestParam String key, @RequestParam Integer value) {
//注意如果是数值类型的字段,一定要转换成数值类型,不可用object接收,不然会转成子串类型,查询不出数据
Query query = Query.query(Criteria.where(key).gt(value));
List<DocumentEntity> entity = myCongoTemplate.find(query, DocumentEntity.class);
return entity;
}
@RequestMapping("/queryData2")
public List<DocumentEntity> queryData2(@RequestBody DocumentEntity example) {
//组合查询两个条件同时满足
//查询以name名称开头,同时age大于,以age倒叙排列
Query query = Query.query(Criteria.where("name").regex("^"+example.getName())
.andOperator(Criteria.where("age").gt(example.getAge()))).
with(new Sort(Sort.Direction.DESC, "age"));
List<DocumentEntity> entity = myCongoTemplate.find(query, DocumentEntity.class);
return entity;
}
@RequestMapping("/queryAllData")
public List<DocumentEntity> queryAllData() {
List<DocumentEntity> all = myCongoTemplate.findAll(DocumentEntity.class);
return all;
}
@RequestMapping("/updateData")
public Long updateData(@RequestParam String key, @RequestParam String value, @RequestParam Integer newValue) {
Query query = Query.query(Criteria.where(key).is(value));
Update update = new Update();
update.set("score", newValue);
UpdateResult updateResult = myCongoTemplate.upsert(query, update, DocumentEntity.class);
log.info("======{}", updateResult.getUpsertedId());
return updateResult.getModifiedCount();
}
@RequestMapping("/deleteData")
public DeleteResult deleteData(@RequestParam String key, @RequestParam Object value) {
Query query = Query.query(Criteria.where(key).is(value));
DeleteResult deleteResult = myCongoTemplate.remove(query, DocumentEntity.class);
return deleteResult;
}
@RequestMapping("/deleteData2")
public DeleteResult deleteData2(@RequestParam String key, @RequestParam Object value) {
Query query = Query.query(Criteria.where(key).is(value));
DeleteResult deleteResult = myCongoTemplate.remove(query, "xx");
return deleteResult;
}
@RequestMapping("/deleteData3")
public DeleteResult deleteData3(@RequestBody DocumentEntity entity) {
//通过Criteria.byExample 进行where设置,mongodb会对实体类字段进行映射
Query query = Query.query(Criteria.byExample(entity));
DeleteResult deleteResult = myCongoTemplate.remove(query, DocumentEntity.class);
return deleteResult;
}
/**
* 聚合操作
* 对字段name进行分组,并统计score的总分数
* .first是要输出的字段。 .as是字段的别名。 输出类型是Map。
* 也可以加个实体类输出类型设置为实体类,但是别名的字段要和实体类的字段保持一致
* 使用TypedAggregation时要传入输入类型。我们数据的类型是DocumentEntity
*
* 也可以使用Aggregation, 它也是要传入输入类型。 如果不想传入输入类型。要指定集合名称。这样mongodb才能针对该集合数据进行聚合操作
*
*
* project:列出所有本次查询的字段,包括查询条件的字段和需要搜索的字段;
* * match:搜索条件criteria
* * unwind:某一个字段是集合,将该字段分解成数组
* * group:分组的字段,以及聚合相关查询
* * sum:求和(同sql查询)
* * count:数量(同sql查询)
* * as:别名(同sql查询)
* * addToSet:将符合的字段值添加到一个集合或数组中
* * sort:排序
* * skip&limit:分页查询
* */
@RequestMapping("/aggregate")
public List<Map> aggregate() {
TypedAggregation aggregation = new TypedAggregation(DocumentEntity.class,
Aggregation.group("name").first("name").as("name")
.sum("score").as("score"),
Aggregation.sort(Sort.Direction.DESC, "score")
);
AggregationResults<Map> aggregate = myCongoTemplate.aggregate(aggregation, Map.class);
List<Map> mappedResults = aggregate.getMappedResults();
log.info("==========={}", aggregate.getServerUsed());
return mappedResults;
}
}
public PageResult<Map> queryTaskInfoPage(TaskInfoQuery taskInfoQuery) {
PageResult pageResult = new PageResult();
pageResult.setPageNo(taskInfoQuery.getPageNo());
//主表查询条件
Criteria mainCriteria = new Criteria();
mainCriteria.and("deleted").is(Deleted.NON_DELETED.getCode());
//子表查询条件
Criteria subCriteria = new Criteria();
subCriteria.and("ts.deleted").is(Deleted.NON_DELETED.getCode());
// 多表关联查询
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("task_sub") // 被关联表[子表]
.localField("taskNo") // 主表关联字段
.foreignField("taskNo") // 被关联字段
.as("ts"); // 子表别名
UnwindOperation taskSubListUni = Aggregation.unwind("ts", true);
MatchOperation mainMatch = Aggregation.match(mainCriteria);
MatchOperation subMatch = Aggregation.match(subCriteria);
Aggregation countAggregation = Aggregation.newAggregation(lookupOperation, taskSubListUni, mainMatch, subMatch, Aggregation.group("taskNo"));
//查询总数
int count = mongoTemplate.aggregate(countAggregation, "task_main", DriverTaskMainEntity.class).getMappedResults().size();
if (count == 0) {
pageResult.setTotal(count);
return pageResult;
}
//根据主任务号分组,并且按计划发车时间正序排列
//使用分组时如果不指定返回的字段,则只返回分组的字段。所以这里用first设置返回的字段,用addToSet设置返回字段为list数组
this.startIndex = this.pageNo <= 1 ? 0: (this.pageNo - 1L) * this.pageSize
Aggregation newAggregation = Aggregation.newAggregation(lookupOperation, taskSubListUni, mainMatch, subMatch,
Aggregation.group("taskNo").first("startTime").as("startTime").addToSet("ts.taskSubNo").as("taskSubNoList"),
Aggregation.sort(Sort.Direction.ASC, "startTime"),
Aggregation.skip(startIndex), Aggregation.limit(pageSize);
List<Map> driverTaskMainList = mongoTemplate.aggregate(newAggregation, "task_main", Map.class).getMappedResults();
pageResult.setItems(driverTaskMainList);
pageResult.setTotal(count);
return pageResult;
}