首发于 netkiller
Spring Data with MongoDB (四)

Spring Data with MongoDB (四)

Spring Data with MongoDB

节选自 《Netkiller Spring Cloud 手札》

mongoTemplate

导入与模板相关的包

import org.springframework.data.mongodb.core.MongoTemplate;

import org.springframework.data.mongodb.core.query.Criteria;

import org.springframework.data.mongodb.core.query.Query;

import org.springframework.data.mongodb.core.query.Update;

注入 MongoTemplate 对象

@Autowired

private MongoTemplate mongoTemplate;

Save 保存

User user = new User();
user.setName("Netkiller"); 
mongoTemplate.save(user, "user"); 

更新数据

user = mongoTemplate.findOne(Query.query(Criteria.where("name").is("Jam")), User.class);
user.setName("Neo");
mongoTemplate.save(user, "user"); 

Insert

User user = new User();
user.setName("Neo");
mongoTemplate.insert(user, "user"); 
BSONObject personBsonObj = BasicDBObjectBuilder.start()
 .add("name","Neo Chen")
 .add("age",27)
 .add("address",null).get();
mongoTemplate.insert(personBsonObj,"personCollection");
document in the db:
db.personCollection.findOne().pretty();
{"age":21,"name":"John Doe";"address":null}* 

updateFirst 修改符合条件第一条记录

updateFirst 修改符合条件第一条记录
Query query = new Query();
query.addCriteria(Criteria.where("name").is("Neo"));
Update update = new Update();
update.set("name", "Netkiller");
mongoTemplate.updateFirst(query, update, User.class); 

updateMulti 修改符合条件的所有

更新所有数据

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Neo"));
Update update = new Update();
update.set("name", "Jerry");
mongoTemplate.updateMulti(query, update, User.class); 

查找并保存

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Luck"));
Update update = new Update();
update.set("name", "Lisa");
User user = mongoTemplate.findAndModify(query, update, User.class); 

upsert - 修改符合条件时如果不存在则添加

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Green"));
Update update = new Update();
update.set("name", "Tom");
mongoTemplate.upsert(query, update, User.class); 
mongoTemplate.upsert(new Query(Criteria.where("age").is("18")), new Update().set("name", "neo"), collectionName); 

删除

User user = new User();
user.setId("5bbf091efd9557069c4a25c5") 
mongoTemplate.remove(user, "user"); 

查找一条数据

public Person findOneByName(String name) {
 Query query = new Query();
 query.addCriteria(Criteria.where("name").is(name));
 return mongoTemplate.findOne(query, Person.class);
} 

查找所有数据

public List<Person> findByName(String name) {
 Query query = new Query();
 query.addCriteria(Criteria.where("name").is(name));
 return mongoTemplate.find(query, Person.class);
} 

Query

翻页

public List<Person> getAllPersonPaginated(int pageNumber, int pageSize) {
 Query query = new Query();
 query.skip(pageNumber * pageSize);
 query.limit(pageSize);
 return mongoTemplate.find(query, Person.class);
} 

between

实现一个区间条件 new Criteria("createdDate").gte(beginDate).lte(endDate)

 public boolean AccountDeposit(Date beginDate, Date endDate) {
 MatchOperation matchOperation = match(new Criteria("createdDate").gte(beginDate).lte(endDate));
 GroupOperation groupOperation = group("loginname").sum("amount").as("amount");
 SortOperation sortOperation = sort(new Sort(Direction.ASC, "loginname"));
 Aggregation aggregation = newAggregation(matchOperation, groupOperation, sortOperation);
 AggregationResults<AccountSettlementDetails> results = mongoTemplate.aggregate(aggregation, AccountSettlementDetails.class, AccountSettlementDetails.class);
 if (results.getMappedResults() != null) {
 log.info(results.getRawResults().get("result").toString());
 for (AccountSettlementDetails settlementDetails : results.getMappedResults()) {
 log.info("{}", settlementDetails.toString());
 return true;
 }

Criteria

is

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Neo"));
List<User> users = mongoTemplate.find(query, User.class); 

Regex 正则表达式搜索

查询以N开头的名字

Query query = new Query();
query.addCriteria(Criteria.where("name").regex("^N"));
List<User> users = mongoTemplate.find(query,User.class); 

查询以o结尾的名字

Query query = new Query();
query.addCriteria(Criteria.where("name").regex("o$"));
List<User> users = mongoTemplate.find(query, User.class);

lt 和 gt

查询年龄小于 < 30 并 > 20 的用户

Query query = new Query();
query.addCriteria(Criteria.where("age").lt(30).gt(20));
List<User> users = mongoTemplate.find(query,User.class);

查找日期范围

Date start = DateUtil.convertStringToDateTime("2014-02-10 20:38:44");
Date end = DateUtil.convertStringToDateTime("2014-02-10 20:38:50");
Query query = new Query();
Criteria criteria = Criteria.where("delflag").is(false);
criteria.and("modifyDate").gte(start).lte(end);
query.addCriteria(criteria);
query.limit(10);

exists()

Query query = new Query();
query.addCriteria(
 new Criteria().andOperator(
 Criteria.where("field1").exists(true),
 Criteria.where("field1").ne(false)
List<Foo> result = mongoTemplate.find(query, Foo.class);
System.out.println("query - " + query.toString());
for (Foo foo : result) {
 System.out.println("result - " + foo);
} 

包含

public List<Person> findByFavoriteBooks(String favoriteBook) {
 Query query = new Query();
 query.addCriteria(Criteria.where("favoriteBooks").in(favoriteBook));
 return mongoTemplate.find(query, Person.class);
} 

Update

set

Update update = new Update();
update.set("name", "Netkiller"); 

追加数据

 Query query = Query.query(Criteria.where("id").is("5bbf091efd9557069c4a25c5"));
 Update update = new Update().push("author", new Author("neo", "chen"));
 mongoTemplate.updateFirst(query, update, Article.class); 

更新数据

 Query query = Query.query(Criteria.where("classId").is("1").and("Students.studentId").is("1"));
 Update update = Update.update("Students.$.name", "lisa");
 mongoTemplate.upsert(query, update, "class");

删除数据

 Query query = Query.query(Criteria.where("classId").is("1").and("Students.studentId").is("3"));
 Update update = new Update();
 update.unset("Students.$");
 mongoTemplate.updateFirst(query, update, "class"); 

inc

public void updateMultiplePersonAge() {
 Query query = new Query();
 Update update = new Update().inc("age", 1);
 mongoTemplate.findAndModify(query, update, Person.class);;
}

update.addToSet

Query query = Query.query(Criteria.where("classId").is("1"));
Student student = new Student("1", "lisa", 3, "girl");
Update update = new Update();
update.addToSet("Students", student);
mongoTemplate.upsert(query, update, "class"); 

BasicUpdate

BasicUpdate 是底层更新可操作,需要手动实现$set等语句

BasicDBObject basicDBObject = new BasicDBObject();  
basicDBObject.put("$set", new BasicDBObject("date","2018-09-09"));  
Update update = new BasicUpdate(basicDBObject);  
mongoTemplate.updateFirst(new Query(Criteria.where("nickname").is("netkiller")), update,collectionName);   

Sort

按照年龄排序

Query query = new Query();
query.with(new Sort(Sort.Direction.ASC, "age"));
List<User> users = mongoTemplate.find(query,User.class);

Query + PageRequest

final Pageable pageableRequest = new PageRequest(0, 2);
Query query = new Query();
query.with(pageableRequest);

newAggregation

 MultilevelDirectSellingAccountRewardsSettlementDetails multilevelDirectSellingAccountRewardsSettlementDetails = new MultilevelDirectSellingAccountRewardsSettlementDetails();
 multilevelDirectSellingAccountRewardsSettlementDetails.setLoginname("111");
 multilevelDirectSellingAccountRewardsSettlementDetails.setPhone("111");
 multilevelDirectSellingAccountRewardsSettlementDetails.setRecommenderLoginname("111");
 multilevelDirectSellingAccountRewardsSettlementDetails.setRecommenderPhone("111");
 multilevelDirectSellingAccountRewardsSettlementDetails.setRecommenderName("Neo");
 multilevelDirectSellingAccountRewardsSettlementDetails.setRecommenderType("客户");
 multilevelDirectSellingAccountRewardsSettlementDetails.setAmount(5.02);
 multilevelDirectSellingAccountRewardsSettlementDetails.setCreatedDate(new Date());
 multilevelDirectSellingAccountRewardsSettlementDetailsRepository.save(multilevelDirectSellingAccountRewardsSettlementDetails);
 Date beginDate = this.getToday("00:00:00");
 Date endDate = this.getToday("23:59:59");
 log.info(beginDate.toString() + " ~ " + endDate.toString());
 GroupOperation groupOperation = group("loginname").sum("amount").as("amount");
 MatchOperation matchOperation = match(new Criteria("createdDate").gte(beginDate).lte(endDate));
 SortOperation sortOperation = sort(new Sort(Direction.ASC, "loginname"));
 Aggregation aggregation = newAggregation(matchOperation, groupOperation, sortOperation);
 AggregationResults<MultilevelDirectSellingAccountRewardsSettlementDetails> results = mongoTemplate.aggregate(aggregation, MultilevelDirectSellingAccountRewardsSettlementDetails.class, MultilevelDirectSellingAccountRewardsSettlementDetails.class); 
 System.out.println(results.getRawResults().get("result").toString());

创建索引

mongoOps.indexOps(User.class).ensureIndex(new Index().on("name", Direction.ASC));

子对象操作

List 类型

package cn.netkiller.api.domain;
import java.util.List;
import javax.persistence.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class Article {
 private String id;
 private String title;
 private String description;
 List<Author> author;
 public static class Author {
 private String id;
 private String firstname;
 private String lastname;
 public Author(String firstname, String lastname) {
 this.firstname = firstname;
 this.lastname = lastname;
}

更新

db.getCollection('foo').update({"author.firstname":"neo"},{"$set":{"author.$.firstname":"netkiller"}})

更新数据

 Query query = Query.query(Criteria.where("author.firstname").is("neo"));
 Update update = new Update().set("author.$.firstname", "netkiller");
 mongoTemplate.updateFirst(query, update, Article.class);

追加数据

 Query query = Query.query(Criteria.where("id").is("5bbf091efd9557069c4a25c5"));
 Update update = new Update().push("author", new Author("neo", "chen"));
 mongoTemplate.updateFirst(query, update, Article.class); 

删除数据

 Query query = Query.query(Criteria.where("id").is("5bbf091efd9557069c4a25c5"));
 Update update = new Update().pull("author", new Author("jerry", "lee"));
 mongoTemplate.updateFirst(query, update, Article.class); 

GeoJson 反序列化

正常情况下是不需要做反序列化操作的。如花你想测试,打印一些信息可以这样做。

package cn.netkiller.api.config;
import java.io.IOException;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
public class GeoJsonDeserializer extends JsonDeserializer<GeoJsonPoint> {
 @Override
 public GeoJsonPoint deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
 final JsonNode tree = jsonParser.getCodec().readTree(jsonParser);
 final String type = tree.get("type").asText();
 final JsonNode coordsNode = tree.get("coordinates");
 System.out.println(tree.toString());
 System.out.println(type);
 System.out.println(coordsNode.toString());
 double x = 0;
 double y = 0;
 if ("Point".equalsIgnoreCase(type)) {
 x = coordsNode.get(0).asDouble();
 y = coordsNode.get(1).asDouble();
 } else {
 System.out.println(String.format("No logic present to deserialize %s ", tree.asText()));
 final GeoJsonPoint point = new GeoJsonPoint(x, y);
 return point;
}

使用 @JsonDeserialize 指定反序列化 Class

@Document
public class Address {