Java中运用MongoTemplate对MongoDB实现增删改查以及聚合查询的使用

在Java中除了使用源生的方式操作MongoDB,还可以使用MongoTemplate封装类。

首先pom中引入依赖

		
		    org.springframework.data
		    spring-data-mongodb
		

大多数情况下,还是使用实体类的方式来封装mongoDB的document,以此来实现一一对应。

@Component
@Document(collection="user")
@Data
public class User{
	private String id;//主键
	
	private String userName;//用户名
	
	private String createBy;//创建人
	
	private Date createTm;//创建时间
	
	private String modifyBy;//修改人
	
	private Date modifyTm;//修改时间
	
}

这里要说明一下,MongoDB的主键是_id,在定义实体类时,可以使用id,方便操作,会自动与数据库对应的。

其中@Document注解是用来指定数据库的collection,这样就知道该去操作哪个collection了。

@Data使用了lombok来自动生成getter、setter、constructor、toString等方法,需要引入依赖

		
			org.projectlombok
			lombok
			false
		

下面介绍最基本的CRUD

新增

	public void saveUser(User user) {
		mongoTemplate.save(user);
	}

在实体类中set好相应的字段,直接调用save方法,调用完成后,user中的id字段会被自动填值,可以取得主键。

查询

Query query = new Query(Criteria.where("userName").is(username));
List users = mongoTemplate.find(query, User.class);

先new一个Query,在构造方法中可以传一个Criteria,作为类似mysql的where语句,可以在后面用.and继续连接。

查询可以使用排序和分页

		query.with(Sort.by(Sort.Order.desc("name")));
		query.skip(0);
		query.limit(1);

这里的with就是指定一个排序策略,skip就是从第几条开始,limit就是一共查多少条

修改


	public void updateUser(User user) {
		Field[] fields=User.class.getDeclaredFields();
		Update update = new Update();
		for(Field field : fields) {
			field.setAccessible(true);
			Object val=null;
			try {
				val = field.get(user);
			} catch (IllegalArgumentException e) {
				e.getMessage();
			} catch (IllegalAccessException e) {
				e.getMessage();
			}
			String key = field.getName();
			if(val!=null&&!"id".equals(key)) {
				update.set(key, val);
			}
		}
		Query query = new Query(Criteria.where("id").is(user.getId()));
		mongoTemplate.updateFirst(query, update, User.class);	
		
	}

这里用到了反射的方法来构造Update对象,也可以要修改哪一列就用update.set(key,val)的方式显式地写

删除

	public void deleteUser(String id) {
		Query query = new Query(Criteria.where("id").is(id));
		mongoTemplate.remove(query, User.class);	
	}

删除一样是用Query对象来声明条件,删除符合条件的document。

下面重点介绍一下复杂查询,会用到Aggregate聚合查询。

假设这样一个场景,MongoDB中存的json字符串含有一个数组,如

{
    "name":"小明",
    "no":"20180105",
    "test":[
        {"subject":"数学",
         "result":98
        },{"subject":"语文",
         "result":80
        },{"subject":"英语",
         "result":91
        }
    ]
},
{
    "name":"小丽",
    "no":"20180106",
    "test":[
        {"subject":"数学",
         "result":92
        },{"subject":"语文",
         "result":95
        },{"subject":"英语",
         "result":93
        }
    ]
}

这里存放的是学生的考试信息,包含姓名、学号和考试成绩,其中考试成绩是一个对象数组,包含了不同学科的考试成绩。

如果想只查询所有学生的数学成绩,用普通的查询方法,会把其他成绩也带出来,如果把数组拆开呢,这里就要使用聚合查询加上$unwind关键字。

Criteria condition = Criteria.where("test.subject").is("数学");       
Aggregation aggregationQuery = Aggregation.newAggregation(Aggregation.unwind("test"),
				Aggregation.match(condition),
				Aggregation.sort(Sort.by(Sort.Order.desc("test.result"))),
				Aggregation.skip((pageNo.longValue()-1L)*pageSize.longValue()),
				Aggregation.limit(pageSize.longValue()));
@SuppressWarnings("rawtypes")
List list = mongoTemplate.aggregate(aggregation, Test.class,Map.class).getMappedResults()

这样就可以查到每个学生的数学成绩,按照成绩倒序排序,并且使用分页。注意,这里查出来的是个Map,并不是实体类。

关于其他的关键字,网上搜索有一大堆,这里就不赘述了。

如果result成绩是用String来存储的,这时候排序字符串可能就会有问题,那该怎么解决呢

可以使用

aggregationQuery = aggregationQuery.withOptions(
new AggregationOptions.Builder()
.collation(Collation.of(new Locale("zh")).
numericOrderingEnabled()).build());

按照字符串数字来进行排序,并指定了是中文。

你可能感兴趣的:(Java,数据库)