MongoDB从入门到实战(十):SpringBoot集成MongoDB(MongoTemplate)

x33g5p2x  于2021-12-25 转载在 Go  
字(12.9k)|赞(0)|评价(0)|浏览(548)

一:MongoTemplate

MongoTemplate 是数据库和代码之间的接口,对数据库的操作都在它里面。

  1. MongoTemplate实现了interface MongoOperations。
  2. MongoDB documents和domain classes之间的映射关系是通过实现了MongoConverter这个interface的类来实现的。
  3. MongoTemplate提供了非常多的操作MongoDB的方法。 它是线程安全的,可以在多线程的情况下使用。
  4. MongoTemplate实现了MongoOperations接口, 此接口定义了众多的操作方法如"find", “findAndModify”, “findOne”, “insert”, “remove”, “save”, “update” and "updateMulti"等。
  5. MongoTemplate转换domain object为DBObject,缺省转换类为MongoMappingConverter,并提供了Query, Criteria, and Update等流式API。

MongoTemplate核心操作类:Criteria和Query

  • Criteria类:封装所有的语句,以方法的形式查询。
  • Query类:将语句进行封装或者添加排序之类的操作。

MongoTemplate相比MongoRepository来说更加好用,MongoTemplate的方法名和MongoDB Shell中的函数名字一致,只要熟悉MongoDB Shel中的函数就可以很轻松的使用MongoTemplate。

二:集成

2.1 pom.xml

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2.2 application.yml

注意:如果密码单独配需要加单引号

spring:
  data:
    mongodb:
      #uri: mongodb://mongo:123456@localhost:27017/test
      host: localhost
      port: 27017
      database: test
      username: mongo
      password: '123456'

2.3 entity

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Address implements Serializable {
    private String province;
    private String city;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    private Integer gender;
}
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "user")
@CompoundIndex( def = "{'id': 1, 'nickname': -1}")
public class User implements Serializable {

    @Id
    private String id;

    @Indexed
    @Field("username")
    private String username;
    private String nickname;
    private Integer age;
    private Date createTime;
    private UserInfo userInfo;
    private List<String> tags;
    private List<Address> addresses;
}
  • @Document(collection = “user”) : 配置集合名字
  • @CompoundIndex( def = “{‘id’: 1, ‘username’: -1}”) : 复合索引
  • @Id : 主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
  • @Field(“字段名”): 该属性对应mongodb的字段的名字,如果一致,则无需该注解
  • @Indexed: 添加了一个单字段的索引

三:MongoTemplate API

3.1 MongoTemplate

操作MongoDB的模板

public class MongoTemplate implements MongoOperations {
	/************************************ 集合操作 ************************************/
	Set<String> getCollectionNames();
	String getCollectionName(Class<?> entityClass);
	DBCollection getCollection(String collectionName);
	<T> DBCollection createCollection(Class<T> entityClass);
	<T> DBCollection createCollection(Class<T> entityClass, CollectionOptions collectionOptions);
	DBCollection createCollection(String collectionName);
	DBCollection createCollection(String collectionName, CollectionOptions collectionOptions);
	<T> boolean collectionExists(Class<T> entityClass);
	boolean collectionExists(String collectionName);
	<T> void dropCollection(Class<T> entityClass);
	void dropCollection(String collectionName);


	/************************************ 保存 ************************************/
	void insert(Object objectToSave);
	void insert(Object objectToSave, String collectionName);
	void insert(Collection<? extends Object> batchToSave, Class<?> entityClass);
	void insert(Collection<? extends Object> batchToSave, String collectionName);
	void insertAll(Collection<? extends Object> objectsToSave);

	void save(Object objectToSave);
	void save(Object objectToSave, String collectionName);


	/****************************** insertOrUpdate *****************************/
	WriteResult upsert(Query query, Update update, Class<?> entityClass);
	WriteResult upsert(Query query, Update update, String collectionName);
	WriteResult upsert(Query query, Update update, Class<?> entityClass, String collectionName);
	
	

	/************************************ 更新 ***********************************/
	WriteResult updateFirst(Query query, Update update, Class<?> entityClass);
	WriteResult updateFirst(Query query, Update update, String collectionName);
	WriteResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
	WriteResult updateMulti(Query query, Update update, Class<?> entityClass);
	WriteResult updateMulti(Query query, Update update, String collectionName);
	WriteResult updateMulti(final Query query, final Update update, Class<?> entityClass, String collectionName);


	/************************************ 查找 ***********************************/
	<T> T findOne(Query query, Class<T> entityClass);
	<T> T findOne(Query query, Class<T> entityClass, String collectionName);
	<T> List<T> findAll(Class<T> entityClass);
	<T> List<T> findAll(Class<T> entityClass, String collectionName);
	<T> List<T> find(Query query, Class<T> entityClass);
	<T> List<T> find(Query query, Class<T> entityClass, String collectionName);
	<T> T findById(Object id, Class<T> entityClass);
	<T> T findById(Object id, Class<T> entityClass, String collectionName);
	<T> T findAndModify(Query query, Update update, Class<T> entityClass);
	<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
	<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
	<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
			String collectionName);
	<T> T findAndRemove(Query query, Class<T> entityClass);
	<T> T findAndRemove(Query query, Class<T> entityClass, String collectionName);

	
	/********************************** 删除 **********************************/
	WriteResult remove(Object object);
	WriteResult remove(Object object, String collection);
	WriteResult remove(Query query, Class<?> entityClass);
	WriteResult remove(Query query, Class<?> entityClass, String collectionName);
	WriteResult remove(Query query, String collectionName);
	
	<T> List<T> findAllAndRemove(Query query, String collectionName);
	<T> List<T> findAllAndRemove(Query query, Class<T> entityClass);
	<T> List<T> findAllAndRemove(Query query, Class<T> entityClass, String collectionName);


	/*********************************** 分组 ***********************************/
	<T> GroupByResults<T> group(String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
	<T> GroupByResults<T> group(Criteria criteria, String inputCollectionName, GroupBy groupBy, Class<T> entityClass);


	/*********************************** 聚合 ***********************************/
	<O> AggregationResults<O> aggregate(TypedAggregation<?> aggregation, String collectionName, Class<O> outputType);
	<O> AggregationResults<O> aggregate(TypedAggregation<?> aggregation, Class<O> outputType);
	<O> AggregationResults<O> aggregate(Aggregation aggregation, Class<?> inputType, Class<O> outputType);
	<O> AggregationResults<O> aggregate(Aggregation aggregation, String collectionName, Class<O> outputType);

	

	<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
			Class<T> entityClass);
	<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
			MapReduceOptions mapReduceOptions, Class<T> entityClass);
	<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction,
			Class<T> entityClass);
	<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction,
			MapReduceOptions mapReduceOptions, Class<T> entityClass);
			

	long count(Query query, Class<?> entityClass);
	long count(Query query, String collectionName);
	long count(Query query, Class<?> entityClass, String collectionName);

	boolean exists(Query query, String collectionName);
	boolean exists(Query query, Class<?> entityClass);
	boolean exists(Query query, Class<?> entityClass, String collectionName);

	
	/*********************************** 地理 ***********************************/		
	<T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass);
	<T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass, String collectionName);
}

3.2 Query

用于构造where条件。

public class Query {
	public static Query query(CriteriaDefinition criteriaDefinition);
	public Query(CriteriaDefinition criteriaDefinition);
	
	public Query addCriteria(CriteriaDefinition criteriaDefinition);
	
	public Query skip(int skip);
	public Query limit(int limit);
	public Query withHint(String name);
	public Query with(Pageable pageable);
	public Query with(Sort sort);
}

3.3 Criteria

用于连接过滤条件。

public class Criteria implements CriteriaDefinition {
	public Criteria(String key);
	public static Criteria where(String key);
	
	public Criteria and(String key);
	public Criteria is(Object o);
	public Criteria ne(Object o);
	public Criteria lt(Object o);
	public Criteria lte(Object o);
	public Criteria gt(Object o);
	public Criteria gte(Object o);
	public Criteria in(Object... o);
	public Criteria nin(Object... o);
	public Criteria not();
	public Criteria regex(String re);
	public Criteria andOperator(Criteria... criteria);
	public Criteria orOperator(Criteria... criteria);
	
	public Criteria mod(Number value, Number remainder);
	public Criteria all(Object... o);
	public Criteria size(int s);
	public Criteria exists(boolean b);
	public Criteria type(int t);
	
}

3.4 Update

用于更新操作。

public class Update {
	public static Update update(String key, Object value);
	public Update set(String key, Object value);
	public Update inc(String key, Number inc);
	public Update push(String key, Object value);
	public Update pop(String key, Position pos);
}

四:Test

@SpringBootTest
@RunWith(SpringRunner.class)
class SpringbootMongodbApplicationTests {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    void testMongoDB() {
        User document = new User();
        document.setId("1");
        document.setUsername("monday");
        document.setNickname("mengday");
        document.setAge(30);
        document.setCreateTime(new Date());
        document.setUserInfo(new UserInfo(1));
        document.setTags(Arrays.asList("xiaojiejie", "dog"));
        document.setAddresses(Arrays.asList(
                new Address("shanghai", "pudong"),
                new Address("beijing", "chaoyang")
        ));

        mongoTemplate.dropCollection(User.class);
        mongoTemplate.save(document);

        // 更新
        Update update = new Update();
        update.set("password", "123456");
        update.inc("age", -1);
        mongoTemplate.updateMulti(new Query(Criteria.where("_id").in("1", "2")), update, User.class);

        
        List<User> findAll = mongoTemplate.findAll(User.class);
        User findById = mongoTemplate.findById("1", User.class);

        // is 相当于SQL中的 =
        // is的值是类型必须和id的数据类型一致
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is("1"));
        User findOne = mongoTemplate.findOne(query, User.class);
        System.out.println(findOne);

        // 左匹配 LIKE 'mon%'
        Pattern pattern = Pattern.compile("^mon.*$", Pattern.CASE_INSENSITIVE);
        Query regexQuery = new Query(Criteria.where("username").regex(pattern));
        List<User> find = mongoTemplate.find(regexQuery, User.class);
        System.out.println(find);
        
        
        // 右匹配 LIKE '%@126.com'
        Pattern pattern = Pattern.compile("^.*@126.com$", Pattern.CASE_INSENSITIVE);
        Query regexQuery = new Query(Criteria.where("email").regex(pattern));
        List<User> findList = mongoTemplate.find(regexQuery, User.class);

        
        
        // 模糊匹配 LIKE '%法%'
        pattern = Pattern.compile("^.法.*$*", Pattern.CASE_INSENSITIVE);
        regexQuery = new Query(Criteria.where("username").regex(pattern));
        findList = mongoTemplate.find(regexQuery, User.class);

        
        
        // 完全匹配 = 'monday'
        pattern = Pattern.compile("^monday$", Pattern.CASE_INSENSITIVE);
        regexQuery = new Query(Criteria.where("username").regex(pattern));
        findList = mongoTemplate.find(regexQuery, User.class);
        

        
        // 多条键查询 andOperator(相当于SQL中的 and并且)
        Criteria andCriatira = new Criteria();
        andCriatira.andOperator(Criteria.where("age").gte(29), Criteria.where("username").is("monday"));
        List<User> find = mongoTemplate.find(new Query(andCriatira), User.class);


        // or
        Criteria orCriatira = new Criteria();
        orCriatira.orOperator(Criteria.where("_id").in("1", "2"), Criteria.where("username").is("monday"));
        List<User> find = mongoTemplate.find(new Query(orCriatira), User.class);

        
        
        // 分页
        int page = 1;
        int pageSize = 5;
        int offset = (page - 1) * pageSize;

        Query query = new Query();
        Sort sort = Sort.by(Sort.Direction.DESC, "_id");
        query.with(sort).skip(offset).limit(pageSize);
        List<User> find = mongoTemplate.find(query, User.class);
        System.out.println(find);

        //封装查询条件
        // Aggregation.group("属性名") 不是字段名,不是_id
        List<AggregationOperation> operations = new ArrayList<>();
        operations.add(Aggregation.match(Criteria.where("_id").is("1")));
        operations.add(Aggregation.group("id").sum("age").as("totalAge"));
        operations.add(Aggregation.sort(Sort.Direction.DESC, "_id"));
        operations.add(Aggregation.skip(1L));
        operations.add(Aggregation.limit(2));
        Aggregation aggregation = Aggregation.newAggregation(operations);

        //查询、并获取结果
        AggregationResults<UserAgg> aggregationResults = mongoTemplate.aggregate(aggregation, User.class, UserAgg.class);
        List<UserAgg> mappedResults = aggregationResults.getMappedResults();
        System.out.println(mappedResults);
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserAgg {
    private String id;
    private Integer totalAge;
}

相关文章