使用Spring Data 框架都是按照面向对象思想操作用于的工具。
使用Spring Data Mongodb 也是使用面向对象的方式进行操作MongoDB,省略了使用Mongodb的Java客户端API把Document转换为实体类的过程;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.5.5</version>
</dependency>
spring:
data:
mongodb:
database: ccc # 操作的库
host: 192.168.2.138
username: readWrite01
password: readWrite01
port: 27017
authentication-database: ccc #认证的库
我演示是在ccc库下的ccc集合操作
@Document("ccc")
public class User implements Serializable {
private static final long serialVersionUID = -2979380902844853046L;
/**
* 主键 主键可以叫做id也能映射上_id
*/
@Id
String id;
/**
* key
*/
String name;
/**
* value
*/
String value;
@Document
参数表示操作的集合名称,如果没有@Document表示操作的集合名为实体类名首字母变小写(由大驼峰变成小驼峰)。@Id
标识主键。当主键叫做_id或id时可以省略此属性@Field
放在普通属性上,如果希望对属性改名或其他限制需要此注解。可以省略,表示实体类属性名为Mongodb集合中field名称insert方法返回值是新增的Document对象,里面包含了新增后_id的值。
如果集合不存在会自动创建集合。
通过Spring Data MongoDB还会给集合中多加一个_class的属性,存储新增时Document对应Java中类的全限定路径。这么做为了查询时能把Document转换为Java中类类型。
@Autowired
MongoTemplate mongoTemplate;
@Test
public void test(){
User user = new User();
user.setName("张三");
user.setValue("张三");
User insert = mongoTemplate.insert(user);
System.out.println("insert = " + insert.toString());
}
在Mongodb中无论是使用客户端API还是使用Spring Data,更新返回结果一定是受影响行数。如果更新后的结果和更新前的结果是相同,返回0。
如果使用对象方式进行修改(save方法)必须要保证对象中所有属性都是有值,否则只能使用update方法
使用save修改
使用save时,如果主键值已经存在,则表示修改操作
@Test
public void saveUser(){
//当明确给定主键时,如果主键值已经存在save表示修改(全量替换)
User user = new User();
user.setId("61ac7634dae9b51c4c658e39");
user.setName("张三01");
// user.setValue("张三01");
User save = mongoTemplate.save(user);
System.out.println("save = " + save.toString());
}
所以使用save时,必须保证全部有值,因为他是全量替换,没给值的会赋null
底层使用mongodb更新运算符完成。
Update的set方法底层就是$set
.可以通过set方法更新特定的属性值。
有两个更新方法:
updateFirst() 只更新满足条件的第一个值
@Test
public void updateOneUser() {
//设置查询体,查询条件具体内容
Criteria criteria = Criteria.where("name").is("张三01");
// query设置查询条件
Query query = new Query(criteria);
// 设置修改哪些属性
Update update = new Update();
update.set("name", "张三02");
update.set("value", "张三02");
// User.class 告诉Spring Data MognoDB 上面的属性是哪个类
// 类对应集合,就知道具体操作集合的哪个属性
UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
// 修改数量,如果修改前后相同,则返回0
long modifiedCount = updateResult.getModifiedCount();
System.out.println("modifiedCount = " + modifiedCount);
// 匹配数量,最多返回1
long matchedCount = updateResult.getMatchedCount();
System.out.println("matchedCount = " + matchedCount);
}
updateMulti () 更新所有满足条件的值
@Test
public void updateMultiUser() {
//设置查询体,查询条件具体内容
Criteria criteria = Criteria.where("name").is("张三02");
// query设置查询条件
Query query = new Query(criteria);
// 设置修改哪些属性
Update update = new Update();
update.set("name", "张三03");
update.set("value", "张三03");
// User.class 告诉Spring Data MognoDB 上面的属性是哪个类
// 类对应集合,就知道具体操作集合的哪个属性
UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
// 修改数量,如果修改前后相同,则返回0
long modifiedCount = updateResult.getModifiedCount();
System.out.println("modifiedCount = " + modifiedCount);
// 匹配数量,最多返回1
long matchedCount = updateResult.getMatchedCount();
System.out.println("matchedCount = " + matchedCount);
}
使用remove(Object)
实现根据主键进行删除。
只判断对象的主键,其他属性是否有值没有影响。但是主键必须不能是null的
@Test
public void removeUser() {
User user = new User();
user.setId("61ac7634dae9b51c4c658e39");
// 根据id主键删除,其他值无所谓
DeleteResult remove = mongoTemplate.remove(user);
long deletedCount = remove.getDeletedCount();
System.out.println("deletedCount = " + deletedCount);
}
只要是Spring Data MongoDB中涉及到条件都提供了两种方式:
比如下面的name ,实体属性名为name ,但是field为 username
@Document("ccc")
public class User implements Serializable {
private static final long serialVersionUID = -2979380902844853046L;
/**
* 主键 主键可以叫做id也能映射上_id
*/
@Id
String id;
/**
* key
*/
@Field("username")
String name;
通过实体类属性名设置条件
Query query = new Query(Criteria.where("name").is("张三"));
// 第二个参数告诉Spring Data Mongodb ,name属性对应的类类型。
DeleteResult result = mongoTemplate.remove(query, User.class);
System.out.println(result.getDeletedCount());
通过集合属性名设置条件
Query query = new Query(Criteria.where("username").is("张三"));
// 第二个参数告诉Spring Data Mongodb ,name属性对应的类类型。
DeleteResult result = mongoTemplate.remove(query,"ccc");
System.out.println(result.getDeletedCount());
Criteria是标准查询的接口,可以引用静态的Criteria.where的把多个条件组合在一起,就可以轻松地将多个方法标准和查询连接起来,方便我们操作查询语句。
@Test
public void queryUser(){
Criteria criteria = Criteria.where("name").is("张三");
Query query = new Query(criteria);
List<User> users = mongoTemplate.find(query,User.class);
System.out.println("users = " + users);
}
@Test
public void queryUsers(){
Criteria criteria = new Criteria().orOperator(Criteria.where("name").is("张三"), Criteria.where("value").is("张三"));
Query query = new Query(criteria);
List<User> users = mongoTemplate.find(query, User.class);
System.out.println("users = " + users);
}
@Test
public void queryAllUsers(){
List<User> users = mongoTemplate.findAll(User.class);
System.out.println("users = " + users);
}
@Test
public void queryOneUser(){
//获取到结果中第一条数据
// new Query() 表示没有条件
User one = mongoTemplate.findOne(new Query(), User.class);
System.out.println("one = " + one);
}
@Test
public void queryById(){
//获取到结果中第一条数据
// new Query() 表示没有条件
User one = mongoTemplate.findById("61ab981e19453644a04231ff", User.class);
System.out.println("one = " + one);
}
@Test
public void exists(){
Query query = new Query(Criteria.where("name").exists(true));
List<User> list = mongoTemplate.find(query, User.class);
System.out.println(list);
}
@Test
public void exists(){
Query query = new Query(Criteria.where("age").gte(1).lte(19));
List<User> list = mongoTemplate.find(query, User.class);
System.out.println(list);
}
@Test
public void regex(){
// java中正则不需要有//
Query query = new Query(Criteria.where("name").regex("张"));
List<User> list = mongoTemplate.find(query, User.class);
System.out.println(list);
}
findDistinct() 参数说明:
@Test
public void findDistinct() {
List<String> list = mongoTemplate.findDistinct(new Query(), "name", User.class, String.class);
System.out.println(list);
}
Sort只有私有构造,但是提供给了静态的by方法
Direction是Sort内部枚举。
age按照那个属性进行排序。属性一定是find方法第二个参数类中的属性。
@Test
public void Sort() {
Query query = new Query(Criteria.where("age").gte(2));
query.with(Sort.by(Sort.Direction.DESC,"age"));
List<User> list = mongoTemplate.find(query, User.class);
System.out.println(list);
}
PageRequest是Pageable接口的实现类。里面有protected的构造方法和名称为of的静态方法。
@Test
public void PageRequest() {
Query query = new Query();
// query.with(PageRequest.of(0,2));
query.with(PageRequest.of(0,2, Sort.Direction.DESC,"age"));
List<User> list = mongoTemplate.find(query, User.class);
System.out.println(list);
}
查询文档总数
@Test
public void TypedAggregation() {
TypedAggregation<User> aggregation = TypedAggregation.newAggregation(User.class,
Aggregation.group().count().as("count"));
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
System.out.println(result.getUniqueMappedResult());
System.out.println(result.getUniqueMappedResult().get("count"));
}
分组计算每组总数
@Test
public void TypedAggregation() {
TypedAggregation<User> aggregation = TypedAggregation.newAggregation(User.class,
Aggregation.group("name").count().as("count"));
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
List<Map> list = result.getMappedResults();
for(Map map : list){
System.out.println(map.get("count")+"---"+map.get("_id"));
}
}
带有查询条件的分组计算
@Test
public void TypedAggregation() {
TypedAggregation<User> aggregation = TypedAggregation.newAggregation(User.class,
Aggregation.match(Criteria.where("name").is("张三")), Aggregation.group("name").count().as("count"));
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
List<Map> list = result.getMappedResults();
for(Map map : list){
System.out.println(map.get("count")+"---"+map.get("_id"));
}
}