一、快速入门
数据结构介绍:人员信息
{ "_id" : ObjectId("59f938235d93fc4af8a37114"), "username" : "lison", "country" : "in11digo", "address" : { "aCode" : "邮编", "add" : "d11pff" }, "favorites" : { "movies" : ["杀破狼2","1dushe","雷神1"], "cites" : ["1sh","1cs","1zz"] }, "age" : 18, "salary":NumberDecimal("2.099"), "lenght" :1.79 }
MongoDB脚本实现
原生Java客户端
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.9.0</version> </dependency>
Tips:
3.5.0最新版本加入了对pojo的支持;
3.5.0最新版本增强对json的支持;
mongodb原生客户端支持两种document和pojo模式的开发;
Doc模式代码
package com.enjoylearning.mongo.test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.bson.Document; import org.bson.conversions.Bson; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mongodb.Block; import com.mongodb.MongoClient; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; import static com.mongodb.client.model.Updates.*; import static com.mongodb.client.model.Filters.*; //原生java驱动 document的操作方式 public class QuickStartJavaDocTest { private static final Logger logger = LoggerFactory.getLogger(QuickStartJavaDocTest.class); //数据库 private MongoDatabase db; //文档集合 private MongoCollection<Document> doc; //连接客户端(内置连接池) private MongoClient client; @Before public void init(){ client = new MongoClient("116.62.222.124",27022); db =client.getDatabase("lison"); doc = db.getCollection("users"); } @Test public void insertDemo(){ Document doc1 = new Document(); doc1.append("username", "cang"); doc1.append("country", "USA"); doc1.append("age", 20); doc1.append("lenght", 1.77f); doc1.append("salary", new BigDecimal("6565.22"));//存金额,使用bigdecimal这个数据类型 //添加“address”子文档 Map<String, String> address1 = new HashMap<String, String>(); address1.put("aCode", "0000"); address1.put("add", "xxx000"); doc1.append("address", address1); //添加“favorites”子文档,其中两个属性是数组 Map<String, Object> favorites1 = new HashMap<String, Object>(); favorites1.put("movies", Arrays.asList("aa","bb")); favorites1.put("cites", Arrays.asList("东莞","东京")); doc1.append("favorites", favorites1); Document doc2 = new Document(); doc2.append("username", "Chen"); doc2.append("country", "China"); doc2.append("age", 30); doc2.append("lenght", 1.77f); doc2.append("salary", new BigDecimal("8888.22")); Map<String, String> address2 = new HashMap<>(); address2.put("aCode", "411000"); address2.put("add", "我的地址2"); doc2.append("address", address2); Map<String, Object> favorites2 = new HashMap<>(); favorites2.put("movies", Arrays.asList("东游记","一路向东")); favorites2.put("cites", Arrays.asList("珠海","东京")); doc2.append("favorites", favorites2); //使用insertMany插入多条数据 doc.insertMany(Arrays.asList(doc1,doc2)); } @Test public void testFind(){ final List<Document> ret = new ArrayList<>(); //block接口专门用于处理查询出来的数据 Block<Document> printBlock = new Block<Document>() { @Override public void apply(Document t) { logger.info(t.toJson());//打印数据 ret.add(t); } }; //select * from users where favorites.cites has "东莞"、"东京" //db.users.find({ "favorites.cites" : { "$all" : [ "东莞" , "东京"]}}) Bson all = all("favorites.cites", Arrays.asList("东莞","东京"));//定义数据过滤器,喜欢的城市中要包含"东莞"、"东京" FindIterable<Document> find = doc.find(all); find.forEach(printBlock); logger.info("------------------>"+String.valueOf(ret.size())); ret.removeAll(ret); //select * from users where username like '%s%' and (contry= English or contry = USA) // db.users.find({ "$and" : [ { "username" : { "$regex" : ".*s.*"}} , { "$or" : [ { "country" : "English"} , { "country" : "USA"}]}]}) String regexStr = ".*s.*"; Bson regex = regex("username", regexStr);//定义数据过滤器,username like '%s%' Bson or = or(eq("country","English"),eq("country","USA"));//定义数据过滤器,(contry= English or contry = USA) Bson and = and(regex,or); FindIterable<Document> find2 = doc.find(and); find2.forEach(printBlock); logger.info("------------------>"+String.valueOf(ret.size())); } @Test public void testUpdate(){ //update users set age=6 where username = 'lison' // db.users.updateMany({ "username" : "lison"},{ "$set" : { "age" : 6}},true) Bson eq = eq("username", "lison");//定义数据过滤器,username = 'lison' Bson set = set("age", 8);//更新的字段.来自于Updates包的静态导入 UpdateResult updateMany = doc.updateMany(eq, set); logger.info("------------------>"+String.valueOf(updateMany.getModifiedCount()));//打印受影响的行数 //update users set favorites.movies add "小电影2 ", "小电影3" where favorites.cites has "东莞" //db.users.updateMany({ "favorites.cites" : "东莞"}, { "$addToSet" : { "favorites.movies" : { "$each" : [ "小电影2 " , "小电影3"]}}},true) Bson eq2 = eq("favorites.cites", "东莞");//定义数据过滤器,favorites.cites has "东莞" Bson addEachToSet = addEachToSet("favorites.movies", Arrays.asList( "小电影2 ", "小电影3"));//更新的字段.来自于Updates包的静态导入 UpdateResult updateMany2 = doc.updateMany(eq2, addEachToSet); logger.info("------------------>"+String.valueOf(updateMany2.getModifiedCount())); } @Test public void testDelete(){ //delete from users where username = ‘lison’ //db.users.deleteMany({ "username" : "lison"} ) Bson eq = eq("username", "lison");//定义数据过滤器,username='lison' DeleteResult deleteMany = doc.deleteMany(eq); logger.info("------------------>"+String.valueOf(deleteMany.getDeletedCount()));//打印受影响的行数 //delete from users where age >8 and age <25 //db.users.deleteMany({"$and" : [ {"age" : {"$gt": 8}} , {"age" : {"$lt" : 25}}]}) Bson gt = gt("age",8);//定义数据过滤器,age > 8,所有过滤器的定义来自于Filter这个包的静态方法,需要频繁使用所以静态导入 // Bson gt = Filter.gt("age",8); Bson lt = lt("age",25);//定义数据过滤器,age < 25 Bson and = and(gt,lt);//定义数据过滤器,将条件用and拼接 DeleteResult deleteMany2 = doc.deleteMany(and); logger.info("------------------>"+String.valueOf(deleteMany2.getDeletedCount()));//打印受影响的行数 } }
POJO模式代码
package com.enjoylearning.mongo.test; import static com.mongodb.client.model.Updates.*; import static com.mongodb.client.model.Filters.*; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.codecs.pojo.PojoCodecProvider; import org.bson.conversions.Bson; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.enjoylearning.mongo.entity.Address; import com.enjoylearning.mongo.entity.Favorites; import com.enjoylearning.mongo.entity.User; import com.mongodb.Block; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.ServerAddress; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; //原生java驱动 Pojo的操作方式 public class QuickStartJavaPojoTest { private static final Logger logger = LoggerFactory.getLogger(QuickStartJavaPojoTest.class); private MongoDatabase db; private MongoCollection<User> doc; private MongoClient client; @Before public void init(){ //编解码器的list List<CodecRegistry> codecResgistes = new ArrayList<>(); //list加入默认的编解码器集合 codecResgistes.add(MongoClient.getDefaultCodecRegistry()); //生成一个pojo的编解码器 CodecRegistry pojoCodecRegistry = CodecRegistries. fromProviders(PojoCodecProvider.builder().automatic(true).build()); //list加入pojo的编解码器 codecResgistes.add(pojoCodecRegistry); //通过编解码器的list生成编解码器注册中心 CodecRegistry registry = CodecRegistries.fromRegistries(codecResgistes); //把编解码器注册中心放入MongoClientOptions //MongoClientOptions相当于连接池的配置信息 MongoClientOptions build = MongoClientOptions.builder(). codecRegistry(registry).build(); ServerAddress serverAddress = new ServerAddress("116.62.222.124",27022); client = new MongoClient(serverAddress, build); db =client.getDatabase("lison"); doc = db.getCollection("users",User.class); } @Test public void insertDemo(){ User user = new User(); user.setUsername("cang"); user.setCountry("USA"); user.setAge(20); user.setLenght(1.77f); user.setSalary(new BigDecimal("6265.22")); //添加“address”子文档 Address address1 = new Address(); address1.setaCode("411222"); address1.setAdd("sdfsdf"); user.setAddress(address1); //添加“favorites”子文档,其中两个属性是数组 Favorites favorites1 = new Favorites(); favorites1.setCites(Arrays.asList("东莞","东京")); favorites1.setMovies(Arrays.asList("西游记","一路向西")); user.setFavorites(favorites1); User user1 = new User(); user1.setUsername("chen"); user1.setCountry("China"); user1.setAge(30); user1.setLenght(1.77f); user1.setSalary(new BigDecimal("6885.22")); Address address2 = new Address(); address2.setaCode("411000"); address2.setAdd("我的地址2"); user1.setAddress(address2); Favorites favorites2 = new Favorites(); favorites2.setCites(Arrays.asList("珠海","东京")); favorites2.setMovies(Arrays.asList("东游记","一路向东")); user1.setFavorites(favorites2); //使用insertMany插入多条数据 doc.insertMany(Arrays.asList(user,user1)); } @Test public void testFind(){ final List<User> ret = new ArrayList<>(); Block<User> printBlock = new Block<User>() { @Override public void apply(User t) { System.out.println(t.toString()); ret.add(t); } }; //select * from users where favorites.cites has "东莞"、"东京" //db.users.find({ "favorites.cites" : { "$all" : [ "东莞" , "东京"]}}) Bson all = all("favorites.cites", Arrays.asList("东莞","东京"));//定义数据过滤器,喜欢的城市中要包含"东莞"、"东京" FindIterable<User> find = doc.find(all); find.forEach(printBlock); logger.info("------------------>"+String.valueOf(ret.size())); ret.removeAll(ret); //select * from users where username like '%s%' and (contry= English or contry = USA) // db.users.find({ "$and" : [ { "username" : { "$regex" : ".*s.*"}} , { "$or" : [ { "country" : "English"} , { "country" : "USA"}]}]}) String regexStr = ".*s.*"; Bson regex = regex("username", regexStr);//定义数据过滤器,username like '%s%' Bson or = or(eq("country","English"),eq("country","USA"));//定义数据过滤器,(contry= English or contry = USA) FindIterable<User> find2 = doc.find(and(regex,or)); find2.forEach(printBlock); logger.info("------------------>"+String.valueOf(ret.size())); } @Test public void testUpdate(){ //update users set age=6 where username = 'lison' //db.users.updateMany({ "username" : "lison"},{ "$set" : { "age" : 6}},true) Bson eq = eq("username", "lison");//定义数据过滤器,username = 'lison' Bson set = set("age", 8);//更新的字段.来自于Updates包的静态导入 UpdateResult updateMany = doc.updateMany(eq, set); logger.info("------------------>"+String.valueOf(updateMany.getModifiedCount()));//打印受影响的行数 //update users set favorites.movies add "小电影2 ", "小电影3" where favorites.cites has "东莞" //db.users.updateMany({ "favorites.cites" : "东莞"}, { "$addToSet" : { "favorites.movies" : { "$each" : [ "小电影2 " , "小电影3"]}}},true) Bson eq2 = eq("favorites.cites", "东莞");//定义数据过滤器,favorites.cites has "东莞" Bson addEachToSet = addEachToSet("favorites.movies", Arrays.asList( "小电影2 ", "小电影3"));//更新的字段.来自于Updates包的静态导入 UpdateResult updateMany2 = doc.updateMany(eq2, addEachToSet); logger.info("------------------>"+String.valueOf(updateMany2.getModifiedCount())); } @Test public void testDelete(){ //delete from users where username = ‘lison’ //db.users.deleteMany({ "username" : "lison"} ) Bson eq = eq("username", "lison");//定义数据过滤器,username='lison' DeleteResult deleteMany = doc.deleteMany(eq); logger.info("------------------>"+String.valueOf(deleteMany.getDeletedCount()));//打印受影响的行数 //delete from users where age >8 and age <25 //db.users.deleteMany({"$and" : [ {"age" : {"$gt": 8}} , {"age" : {"$lt" : 25}}]}) Bson gt = gt("age",8);//定义数据过滤器,age > 8,所有过滤器的定义来自于Filter这个包的静态方法,需要频繁使用所以静态导入 Bson lt = lt("age",25);//定义数据过滤器,age < 25 Bson and = and(gt,lt);//定义数据过滤器,将条件用and拼接 DeleteResult deleteMany2 = doc.deleteMany(and); logger.info("------------------>"+String.valueOf(deleteMany2.getDeletedCount()));//打印受影响的行数 } }
Spring-data-mongodb客户端
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.10.18.RELEASE</version> </dependency>
Tips:
spring-data-mongodb的最新版本是2.x.x,如果是spring为5.0版本以上的才推荐使用;
spring-data-mongodb的1.10.18版本基于spring4.3.x开发,但是默认依赖的mongodb驱动为2.14.3,可以将mongodb的驱动设置为3.9.0的版本;
spring-data-mongodb一般使用pojo的方式开发;
Spring POJO开发模式代码
package com.enjoylearning.mongo.test; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.enjoylearning.mongo.entity.Address; import com.enjoylearning.mongo.entity.Favorites; import com.enjoylearning.mongo.entity.User; import com.mongodb.WriteResult; //spring Pojo的操作方式 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class QuickStartSpringPojoTest { private static final Logger logger = LoggerFactory.getLogger(QuickStartSpringPojoTest.class); @Resource private MongoOperations tempelate; @Test public void insertDemo(){ User user = new User(); user.setUsername("cang"); user.setCountry("USA"); user.setAge(20); user.setLenght(1.77f); user.setSalary(new BigDecimal("6265.22")); //添加“address”子文档 Address address1 = new Address(); address1.setaCode("411222"); address1.setAdd("sdfsdf"); user.setAddress(address1); //添加“favorites”子文档,其中两个属性是数组 Favorites favorites1 = new Favorites(); favorites1.setCites(Arrays.asList("东莞","东京")); favorites1.setMovies(Arrays.asList("西游记","一路向西")); user.setFavorites(favorites1); User user1 = new User(); user1.setUsername("chen"); user1.setCountry("China"); user1.setAge(30); user1.setLenght(1.77f); user1.setSalary(new BigDecimal("6885.22")); Address address2 = new Address(); address2.setaCode("411000"); address2.setAdd("我的地址2"); user1.setAddress(address2); Favorites favorites2 = new Favorites(); favorites2.setCites(Arrays.asList("珠海","东京")); favorites2.setMovies(Arrays.asList("东游记","一路向东")); user1.setFavorites(favorites2); tempelate.insertAll(Arrays.asList(user,user1)); } @Test public void testFind(){ //select * from users where favorites.cites has "东莞"、"东京" //db.users.find({ "favorites.cites" : { "$all" : [ "东莞" , "东京"]}}) Criteria all = where("favorites.cites").all(Arrays.asList("东莞","东京")); List<User> find = tempelate.find(query(all), User.class); System.out.println(find.size()); for (User user : find) { System.out.println(user.toString()); } //select * from users where username like '%s%' and (contry= English or contry = USA) // db.users.find({ "$and" : [ { "username" : { "$regex" : ".*s.*"}} , { "$or" : [ { "country" : "English"} , { "country" : "USA"}]}]}) String regexStr = ".*s.*"; //username like '%s%' Criteria regex = where("username").regex(regexStr); //contry= EngLish Criteria or1 = where("country").is("English"); //contry= USA Criteria or2 = where("country").is("USA"); Criteria or = new Criteria().orOperator(or1,or2); Query query = query(new Criteria().andOperator(regex,or)); List<User> find2 = tempelate.find(query, User.class); System.out.println(find2.size()); for (User user : find2) { System.out.println(user.toString()); } } @Test public void testUpdate(){ //update users set age=6 where username = 'lison' //db.users.updateMany({ "username" : "lison"},{ "$set" : { "age" : 6}},true) Query query = query(where("username").is("lison")); Update update = update("age", 6); WriteResult updateFirst = tempelate.updateMulti(query, update, User.class); System.out.println(updateFirst.getN()); //update users set favorites.movies add "小电影2 ", "小电影3" where favorites.cites has "东莞" //db.users.updateMany({ "favorites.cites" : "东莞"}, { "$addToSet" : { "favorites.movies" : { "$each" : [ "小电影2 " , "小电影3"]}}},true) query = query(where("favorites.cites").is("东莞")); update = new Update().addToSet("favorites.movies").each("小电影2 ", "小电影3"); WriteResult updateMulti = tempelate.updateMulti(query, update, User.class); System.out.println("--------------------->"+updateMulti.getN()); } @Test public void testDelete(){ //delete from users where username = ‘lison’ //db.users.deleteMany({ "username" : "lison"} ) Query query = query(where("username").is("lison")); WriteResult remove = tempelate.remove(query, User.class); System.out.println("--------------------->"+remove.getN()); //delete from users where age >8 and age <25 //db.users.deleteMany({"$and" : [ {"age" : {"$gt": 8}} , {"age" : {"$lt" : 25}}]}) query = query(new Criteria().andOperator(where("age").gt(8),where("age").lt(25))); WriteResult remove2 = tempelate.remove(query, User.class); System.out.println("--------------------->"+remove2.getN()); } }
开发框架版本选择
Java驱动与MongoDB兼容性
Tips: 考虑到MongoDB客户端强大的向下兼容性,建议使用3.9.0版本
spring data mongo 与java mongo驱动兼容性
Tips:Spring Data MongoDB 1.x 与 2.x之间区别比较大,请点击我
想要使用spring mongoDB 2.x的新API,同时想使用3.5.0以上版本的java驱动?
spring-data-mongodb的1.10.18版本
java mongodb client 3.9
spring 4.3.13以上
MongoDB数据类型
二、查询
查询概要
MongoDB 查询数据的语法格式如下:
db.collection.find(query, projection)
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
注意:0表示字段排除,非0表示字段选择并排除其他字段,所有字段必须设置同样的值;
需要以易读的方式来读取数据,可以使用 pretty() 方法;
举例子:db.users.find({"$and":[{"username":"lison"},{"age":18}]},{"username":0,"age":0})
查询选择器
查询选择器实战
(1)client指定端口和ip连接mongodb
./mongo localhost:27022
(2)in选择器示例:
db.users.find({"username":{"$in":["lison", "mark", "james"]}}).pretty()
查询姓名为lison、mark和james这个范围的人
(3)exists选择器示例:
db.users.find({"lenght":{"$exists":true}}).pretty()
判断文档有没有关心的字段
(4)not选择器示例:
db.users.find({"lenght":{"$not":{"$gte":1.77}}}).pretty()
查询高度小于1.77或者没有身高的人
not语句 会把不包含查询语句字段的文档 也检索出来
查询选择
映射
字段选择并排除其他字段:db.users.find({},{'username':1})
字段排除:db.users.find({},{'username':0})
排序
sort():db.users.find().sort({"username":1}).pretty()
1:升序 -1:降序
跳过和限制
skip(n):跳过n条数据
limit(n):限制n条数据
e.g: db.users.find().sort({"username":1}).limit(2).skip(2)
查询唯一值
distinct():查询指定字段的唯一值,e.g:db.users.distinct("username")
字符串数组选择查询
1.数组单元素查询
db.users.find({"favorites.movies":"蜘蛛侠"})
查询数组中包含"蜘蛛侠"
2.数组精确查找
db.users.find({"favorites.movies":[ "杀破狼2", "战狼", "雷神1" ]},{"favorites.movies":1})
查询数组等于[ "杀破狼2", "战狼", "雷神1" ]的文档,严格按照数量、顺序;
3.数组多元素查询
db.users.find({"favorites.movies":{"$all":[ "雷神1", "战狼" ]}},{"favorites.movies":1})
查询数组包含["雷神1", "战狼" ]的文档,跟顺序无关,跟数量有关
db.users.find({"favorites.movies":{"$in":[ "雷神1", "战狼" ]}},{"favorites.movies":1})
查询数组包含["雷神1", "战狼" ]中任意一个的文档,跟顺序无关,跟数量无关
4.索引查询
db.users.find({"favorites.movies.0":"妇联4"},{"favorites.movies":1})
查询数组中第一个为"妇联4"的文档
5.返回数组子集
db.users.find({},{"favorites.movies":{"$slice":[1,2]},"favorites":1})
$slice可以取两个元素数组,分别表示跳过和限制的条数;
对象数组选择查询
1. 单元素查询
db.users.find({"comments":{
"author" : "lison6",
"content" : "lison评论6","commentTime" : ISODate("2017-06-06T00:00:00Z")}})
备注:对象数组精确查找
2.查找lison1 或者 lison12评论过的user ($in查找符)
db.users.find({"comments.author":{"$in":["lison1","lison12"]}}).pretty()
备注:跟数量无关,跟顺序无关;
3.查找lison1 和 lison12都评论过的user
db.users.find({"comments.author":{"$all":["lison12","lison1"]}}).pretty()
备注:跟数量有关,跟顺序无关;
4.查找lison5评语为包含"苍老师"关键字的user($elemMatch查找符)
db.users.find({"comments":{"$elemMatch":{"author" : "lison5",
"content" : { "$regex" : ".*苍老师.*"}}}}) .pretty()
备注:数组中对象数据要符合查询对象里面所有的字段,$全元素匹配,和顺序无关;
Java客户端解析
原生Java驱动
MongoClient → MongoDatabase →MongoCollection
MongoClient被设计成线程安全、可以被多线程共享的。通常访问数据库集群的应用只需要一个实例
如果需要使用pojo对象读写,需要将PojoCodecProvider注入到client中
查询和更新的API类
查询器:com.mongodb.client.model.Filters
更新器:com.mongodb.client.model.Updates
投影器:com.mongodb.client.model.Projections
package com.enjoylearning.lison.mongodb; import static com.mongodb.client.model.Filters.*; import static com.mongodb.client.model.Projections.*; import static com.mongodb.client.model.Sorts.*; import static com.mongodb.client.model.Aggregates.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.bson.BSON; import org.bson.BsonDocument; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.codecs.pojo.PojoCodecProvider; import org.bson.conversions.Bson; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.manipulation.Filter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.mongodb.Block; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; import com.mongodb.client.AggregateIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Accumulators; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; import com.mongodb.client.model.PushOptions; import com.mongodb.client.model.Updates; import com.mongodb.client.result.UpdateResult; import com.mongodb.operation.OrderBy; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class JavaQueryTest { private static final Logger logger = LoggerFactory .getLogger(JavaQueryTest.class); private MongoDatabase db; private MongoCollection<Document> collection; private MongoCollection<Document> orderCollection; @Resource(name="mongo") private MongoClient client; @Before public void init() { db = client.getDatabase("lison"); collection = db.getCollection("users"); orderCollection = db.getCollection("ordersTest"); } // -----------------------------操作符使用实例------------------------------------------ // db.users.find({"username":{"$in":["lison", "mark", "james"]}}).pretty() // 查询姓名为lison、mark和james这个范围的人 @Test public void testInOper() { Bson in = in("username", "lison", "mark", "james"); FindIterable<Document> find = collection.find(in); printOperation(find); } // db.users.find({"lenght":{"$exists":true}}).pretty() // 判断文档有没有关心的字段 @Test public void testExistsOper() { Bson exists = exists("lenght", true); FindIterable<Document> find = collection.find(exists); printOperation(find); } // db.users.find().sort({"username":1}).limit(1).skip(2) // 测试sort,limit,skip @Test public void testSLSOper() { Document sort = new Document("username", 1); FindIterable<Document> find = collection.find().sort(sort).limit(1).skip(2); printOperation(find); } // db.users.find({"lenght":{"$not":{"$gte":1.77}}}).pretty() // 查询高度小于1.77或者没有身高的人 // not语句 会把不包含查询语句字段的文档 也检索出来 @Test public void testNotOper() { Bson gte = gte("lenght", 1.77); Bson not = not(gte); FindIterable<Document> find = collection.find(not); printOperation(find); } // -----------------------------字符串数组查询实例------------------------------------------ // db.users.find({"favorites.movies":"蜘蛛侠"}) // 查询数组中包含"蜘蛛侠" @Test public void testArray1() { Bson eq = eq("favorites.movies", "蜘蛛侠"); FindIterable<Document> find = collection.find(eq); printOperation(find); } // db.users.find({"favorites.movies":[ "妇联4","杀破狼2", "战狼", "雷神1","神奇动物在哪里"]},{"favorites.movies":1}) // 查询数组等于[ “杀破狼2”, “战狼”, “雷神1” ]的文档,严格按照数量、顺序; @Test public void testArray2() { Bson eq = eq("favorites.movies", Arrays.asList("妇联4","杀破狼2", "战狼", "雷神1","神奇动物在哪里")); FindIterable<Document> find = collection.find(eq); printOperation(find); } //数组多元素查询 @Test public void testArray3() { // db.users.find({"favorites.movies":{"$all":[ "雷神1", "战狼"]}},{"favorites.movies":1}) // 查询数组包含["雷神1", "战狼" ]的文档,跟顺序无关 Bson all = all("favorites.movies", Arrays.asList("雷神1", "战狼")); FindIterable<Document> find = collection.find(all); printOperation(find); // db.users.find({"favorites.movies":{"$in":[ "雷神1", "战狼" ]}},{"favorites.movies":1}) // 查询数组包含[“雷神1”, “战狼” ]中任意一个的文档,跟顺序无关,跟数量无关 Bson in = in("favorites.movies", Arrays.asList("雷神1", "战狼")); find = collection.find(in); printOperation(find); } // // db.users.find({"favorites.movies.0":"妇联4"},{"favorites.movies":1}) // 查询数组中第一个为"妇联4"的文档 @Test public void testArray4() { Bson eq = eq("favorites.movies.0", "妇联4"); FindIterable<Document> find = collection.find(eq); printOperation(find); } // db.users.find({},{"favorites.movies":{"$slice":[1,2]},"favorites":1}) // $slice可以取两个元素数组,分别表示跳过和限制的条数; @Test public void testArray5() { Bson slice = slice("favorites.movies", 1, 2); Bson include = include("favorites"); Bson projection = fields(slice, include); FindIterable<Document> find = collection.find().projection(projection); printOperation(find); } // -----------------------------对象数组查询实例------------------------------------------ //db.users.find({"comments":{"author":"lison6","content":"lison评论6","commentTime":ISODate("2017-06-06T00:00:00Z")}}) //备注:对象数组精确查找 @Test public void testObjArray1() throws ParseException { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date commentDate = formatter.parse("2017-06-06 08:00:00"); Document comment = new Document().append("author", "lison6") .append("content", "lison评论6") .append("commentTime", commentDate); Bson eq = eq("comments", comment); FindIterable<Document> find = collection.find(eq); printOperation(find); } //数组多元素查询 @Test public void testObjArray2() { // 查找lison1 或者 lison12评论过的user ($in查找符) // db.users.find({"comments.author":{"$in":["lison1","lison12"]}}).pretty() // 备注:跟数量无关,跟顺序无关; Bson in = in("comments.author", Arrays.asList("lison1","lison12")); FindIterable<Document> find = collection.find(in); printOperation(find); // 查找lison1 和 lison12都评论过的user // db.users.find({"comments.author":{"$all":["lison12","lison1"]}}).pretty() // 备注:跟数量有关,跟顺序无关; Bson all = all("comments.author", Arrays.asList("lison12","lison1")); find = collection.find(all); printOperation(find); } //查找lison5评语为包含“苍老师”关键字的user($elemMatch查找符) // db.users.find({"comments":{"$elemMatch":{"author" : "lison5", "content" : { "$regex" : ".*苍老师.*"}}}}) //备注:数组中对象数据要符合查询对象里面所有的字段,$全元素匹配,和顺序无关; @Test public void testObjArray3() throws ParseException { Bson eq = eq("author","lison5"); Bson regex = regex("content", ".*苍老师.*"); Bson elemMatch = Filters.elemMatch("comments", and(eq,regex)); FindIterable<Document> find = collection.find(elemMatch); printOperation(find); } // dbRef测试 // dbref其实就是关联关系的信息载体,本身并不会去关联数据 @Test public void dbRefTest() { FindIterable<Document> find = collection.find(eq("username", "lison")); printOperation(find); } // --------------------------------------------------------------------------- //返回对象的处理器,打印每一行数据 private Block<Document> getBlock(final List<Document> ret) { Block<Document> printBlock = new Block<Document>() { @Override public void apply(Document t) { logger.info("---------------------"); logger.info(t.toJson()); logger.info("---------------------"); ret.add(t); } }; return printBlock; } //打印查询出来的数据和查询的数据量 private void printOperation( FindIterable<Document> find) { final List<Document> ret = new ArrayList<Document>(); Block<Document> printBlock = getBlock(ret); find.forEach(printBlock); System.out.println(ret.size()); ret.removeAll(ret); } private void printOperation(List<Document> ret, Block<Document> printBlock, AggregateIterable<Document> aggregate) { aggregate.forEach(printBlock); System.out.println(ret.size()); ret.removeAll(ret); } @Test // 测试elemMatch操作符,数组中对象数据要符合查询对象里面所有的字段 // 查找lison5评语为“lison是苍老师的小迷弟”的人 // db.users.find({"comments":{"$elemMatch":{"author" : "lison5","content" : // "lison是苍老师的小迷弟"}}}) .pretty() public void testElemMatch() { Document filter = new Document().append("author", "lison5").append( "content", "lison是苍老师的小迷弟"); Bson elemMatch = Filters.elemMatch("comments", filter); FindIterable<Document> find = collection.find(elemMatch); printOperation(find); } /** * db.users.updateOne({"username":"lison",}, {"$push": { "comments": { * $each: [{ "author" : "james", "content" : "lison是个好老师!", "commentTime" : * ISODate("2018-01-06T04:26:18.354Z") } ], $sort: {"commentTime":-1} }}}); */ @Test // 新增评论时,使用$sort运算符进行排序,插入评论后,再按照评论时间降序排序 public void demoStep1() { Bson filter = eq("username", "lison"); Document comment = new Document().append("author", "cang") .append("content", "lison是我的粉丝") .append("commentTime", new Date()); // $sort: {"commentTime":-1} Document sortDoc = new Document().append("commentTime", -1); PushOptions sortDocument = new PushOptions().sortDocument(sortDoc); // $each Bson pushEach = Updates.pushEach("comments", Arrays.asList(comment), sortDocument); UpdateResult updateOne = collection.updateOne(filter, pushEach); System.out.println(updateOne.getModifiedCount()); } @Test // 查看人员时加载最新的三条评论; // db.users.find({"username":"lison"},{"comments":{"$slice":[0,3]}}).pretty() public void demoStep2() { FindIterable<Document> find = collection.find(eq("username", "lison")) .projection(slice("comments", 0, 3)); printOperation(find); } @Test // 点击评论的下一页按钮,新加载三条评论 // db.users.find({"username":"lison"},{"comments":{"$slice":[3,3]},"$id":1}).pretty(); public void demoStep3() { // {"username":"lison"} Bson filter = eq("username", "lison"); // "$slice":[3,3] Bson slice = slice("comments", 3, 3); // "$id":1 Bson includeID = include("id"); // {"comments":{"$slice":[3,3]},"$id":1}) Bson projection = fields(slice, includeID); FindIterable<Document> find = collection.find(filter).projection( projection); printOperation(find); } @Test /** * db.users.aggregate([{"$match":{"username":"lison"}}, {"$unwind":"$comments"}, {$sort:{"comments.commentTime":-1}}, {"$project":{"comments":1}}, {"$skip":6}, {"$limit":3}]) */ // 如果有多种排序需求怎么处理,使用聚合 public void demoStep4() { final List<Document> ret = new ArrayList<Document>(); Block<Document> printBlock = getBlock(ret); List<Bson> aggregates = new ArrayList<Bson>(); aggregates.add(match(eq("username", "lison"))); aggregates.add(unwind("$comments")); aggregates.add(sort(orderBy(ascending("comments.commentTime")))); aggregates.add(project(fields(include("comments")))); aggregates.add(skip(0)); aggregates.add(limit(3)); AggregateIterable<Document> aggregate = collection .aggregate(aggregates); printOperation(ret, printBlock, aggregate); } @Test public void aggretionTest() { Block<Document> printBlock = new Block<Document>() { @Override public void apply(Document t) { logger.info("---------------------"); System.out.println(t.toJson()); logger.info("---------------------"); } }; // 定义数据的处理类 // final List<Document> ret = new ArrayList<Document>(); // // // Document filter = new Document().append("useCode","tony"); // // FindIterable<Document> find = orderCollection.find(filter); // // printOperation(ret, printBlock, find); // db.ordersTest.aggregate([{"$group":{_id:"$useCode",count: { $sum: // "$price" } } }]) List<Bson> aggregates = new ArrayList<Bson>(); aggregates.add(group("$useCode", Accumulators.sum("sum", "$price"))); AggregateIterable<Document> aggregate = orderCollection .aggregate(aggregates); aggregate.forEach(printBlock); } }
Spring MongoDB解析
Xml配置文件
<!-- mongodb连接池配置 --> <mongo:mongo-client host="192.168.1.129" port="27017"> <mongo:client-options write-concern="ACKNOWLEDGED" connections-per-host="100" threads-allowed-to-block-for-connection-multiplier="5" max-wait-time="120000" connect-timeout="10000"/> </mongo:mongo-client>> <!-- mongodb数据库工厂配置 --> <mongo:db-factory dbname="lison" mongo-ref="mongo" /> <!-- mongodb模板配置 --> <bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <property name="writeResultChecking" value="EXCEPTION"></property> </bean>
Spring mongodb开发
模板模式,基于MongoOperations进行操作,基于pojo的操作,配合@document注解开发;
查询和更新的API类
查询器:org.springframework.data.mongodb.core.query.Query
查询条件:org.springframework.data.mongodb.core.query.Criteria
更新器:org.springframework.data.mongodb.core.query.Update
Spring实现代码
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd"> <!-- <context:property-placeholder location="classpath:/com/myapp/mongodb/config/mongo.properties" /> --> <context:component-scan base-package="com.enjoylearning.mongo.config"> </context:component-scan> <!-- mongodb连接池配置 --> <!-- <mongo:mongo-client host="192.168.1.142" port="27022" credentials="lison:lison@lison"> --> <mongo:mongo-client host="116.62.222.124" port="27022" > <!-- replica-set="192.168.1.142:27017,192.168.1.142:27018,192.168.1.142:27017" --> <mongo:client-options write-concern="ACKNOWLEDGED" connections-per-host="1" threads-allowed-to-block-for-connection-multiplier="5" max-wait-time="120000" connect-timeout="10000"/> </mongo:mongo-client> <!-- mongodb数据库工厂配置 --> <mongo:db-factory dbname="lison" mongo-ref="mongo" /> <mongo:mapping-converter base-package="com.enjoylearning.mongodb.entity"> <mongo:custom-converters> <mongo:converter> <bean class="com.enjoylearning.mongo.convert.BigDecimalToDecimal128Converter"/> </mongo:converter> <mongo:converter> <bean class="com.enjoylearning.mongo.convert.Decimal128ToBigDecimalConverter"/> </mongo:converter> </mongo:custom-converters> </mongo:mapping-converter> <!-- mongodb模板配置 --> <bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mongoConverter" ref="mappingConverter"/> <property name="writeResultChecking" value="EXCEPTION"></property> </bean> </beans>
package com.enjoylearning.lison.mongodb; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.bson.Document; import org.bson.conversions.Bson; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update.PushOperatorBuilder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.enjoylearning.mongo.entity.Comment; import com.enjoylearning.mongo.entity.User; import com.mongodb.Block; import com.mongodb.WriteResult; import com.mongodb.client.FindIterable; import com.mongodb.client.model.Filters; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringQueryTest { private static final Logger logger = LoggerFactory .getLogger(SpringQueryTest.class); @Resource private MongoOperations tempelate; // -----------------------------操作符使用实例------------------------------------------ // db.users.find({"username":{"$in":["lison", "mark", "james"]}}).pretty() // 查询姓名为lison、mark和james这个范围的人 @Test public void testInOper() { Query query = query(where("username").in("lison", "mark", "james")); List<User> find = tempelate.find(query, User.class); printUsers(find); } // db.users.find({"lenght":{"$exists":true}}).pretty() // 判断文档有没有关心的字段 @Test public void testExistsOper() { Query query = query(where("lenght").exists(true)); List<User> find = tempelate.find(query, User.class); printUsers(find); } // db.users.find().sort({"username":1}).limit(1).skip(2) // 测试sort,limit,skip @Test public void testSLSOper() { Query query = query(where(null)).with(new Sort(new Sort.Order(Direction.ASC, "username"))).limit(1).skip(2); List<User> find = tempelate.find(query, User.class); printUsers(find); } // db.users.find({"lenght":{"$not":{"$gte":1.77}}}).pretty() // 查询高度小于1.77或者没有身高的人 // not语句 会把不包含查询语句字段的文档 也检索出来 @Test public void testNotOper() { Query query = query(where("lenght").not().gte(1.77)); List<User> find = tempelate.find(query, User.class); printUsers(find); } // -----------------------------字符串数组查询实例------------------------------------------ // db.users.find({"favorites.movies":"蜘蛛侠"}) // 查询数组中包含"蜘蛛侠" @Test public void testArray1() { Query query = query(where("favorites.movies").is("蜘蛛侠")); List<User> find = tempelate.find(query, User.class); printUsers(find); } // db.users.find({"favorites.movies":[ "妇联4","杀破狼2", "战狼", "雷神1","神奇动物在哪里"]},{"favorites.movies":1}) // 查询数组等于[ “杀破狼2”, “战狼”, “雷神1” ]的文档,严格按照数量、顺序; @Test public void testArray2() { Query query = query(where("favorites.movies").is(Arrays.asList("妇联4","杀破狼2", "战狼", "雷神1","神奇动物在哪里"))); List<User> find = tempelate.find(query, User.class); printUsers(find); } //数组多元素查询 @Test public void testArray3() { // db.users.find({"favorites.movies":{"$all":[ "雷神1", "战狼"]}},{"favorites.movies":1}) // 查询数组包含["雷神1", "战狼" ]的文档,跟顺序无关 Query query = query(where("favorites.movies").all(Arrays.asList("雷神1", "战狼"))); List<User> find = tempelate.find(query, User.class); printUsers(find); // db.users.find({"favorites.movies":{"$in":[ "雷神1", "战狼" ]}},{"favorites.movies":1}) // 查询数组包含[“雷神1”, “战狼” ]中任意一个的文档,跟顺序无关,跟数量无关 query = query(where("favorites.movies").in(Arrays.asList("雷神1", "战狼"))); find = tempelate.find(query, User.class); printUsers(find); } // // db.users.find({"favorites.movies.0":"妇联4"},{"favorites.movies":1}) // 查询数组中第一个为"妇联4"的文档 @Test public void testArray4() { Query query = query(where("favorites.movies.0").is("妇联4")); List<User> find = tempelate.find(query, User.class); printUsers(find); } // db.users.find({},{"favorites.movies":{"$slice":[1,2]},"favorites":1}) // $slice可以取两个元素数组,分别表示跳过和限制的条数; @Test public void testArray5() { Query query = query(where(null)); query.fields().include("favorites").slice("favorites.movies", 1, 2); List<User> find = tempelate.find(query, User.class); printUsers(find); } // -----------------------------对象数组查询实例------------------------------------------ //db.users.find({"comments":{"author":"lison6","content":"lison评论6","commentTime":ISODate("2017-06-06T00:00:00Z")}}) //备注:对象数组精确查找 //坑:居然和属性定义的顺序有关 @Test public void testObjArray1() throws ParseException { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date commentDate = formatter.parse("2017-06-06 08:00:00"); Comment comment = new Comment(); comment.setAuthor("lison6"); comment.setCommentTime(commentDate); comment.setContent("lison评论6"); Query query = query(where("comments").is(comment)); List<User> find = tempelate.find(query, User.class); printUsers(find); } //数组多元素查询 @Test public void testObjArray2() { // 查找lison1 或者 lison12评论过的user ($in查找符) // db.users.find({"comments.author":{"$in":["lison1","lison12"]}}).pretty() // 备注:跟数量无关,跟顺序无关; Query query = query(where("comments.author").in(Arrays.asList("lison1","lison12"))); List<User> find = tempelate.find(query, User.class); printUsers(find); // 查找lison1 和 lison12都评论过的user // db.users.find({"comments.author":{"$all":["lison12","lison1"]}}).pretty() // 备注:跟数量有关,跟顺序无关; query = query(where("comments.author").all(Arrays.asList("lison1","lison12"))); find = tempelate.find(query, User.class); printUsers(find); } @Test //(1)注意相关的实体bean要加上注解@document,@dbRef //(2)spring对dbRef进行了封装,发起了两次查询请求 public void dbRefTest(){ System.out.println("----------------------------"); List<User> users = tempelate.findAll(User.class); System.out.println("----------------------------"); System.out.println(users); // System.out.println(users.get(0).getComments()); } private void printUsers(List<User> find) { for (User user : find) { System.out.println(user); } System.out.println(find.size()); } //--------------------------------------------------------- //查找lison5评语为包含“苍老师”关键字的user($elemMatch查找符) // db.users.find({"comments":{"$elemMatch":{"author" : "lison5", "content" : { "$regex" : ".*苍老师.*"}}}}) //备注:数组中对象数据要符合查询对象里面所有的字段,$全元素匹配,和顺序无关; @Test public void testObjArray3() throws ParseException { // and(where("author").is("lison5"),where("content").regex(".*苍老师.*"))) Criteria andOperator = new Criteria().andOperator(where("author").is("lison5"),where("content").regex(".*苍老师.*")); Query query = query(where("comments").elemMatch(andOperator)); List<User> find = tempelate.find(query, User.class); printUsers(find); } @Test // db.users.find({"comments":{"$elemMatch":{"author" : "lison5","content" : // "lison是苍老师的小迷弟"}}}) .pretty() public void testElemMatch() { Query query = query(where("comments").elemMatch(where("author").is("lison5").and("content").is("lison是苍老师的小迷弟"))); List<User> find = tempelate.find(query, User.class); System.out.println(find.size()); } /** * db.users.updateOne({"username":"lison",}, {"$push": { "comments": { $each: [{ "author" : "james", "content" : "lison是个好老师!", "commentTime" : ISODate("2018-01-06T04:26:18.354Z") } ], $sort: {"commentTime":-1} }}}); */ @Test // 新增评论时,使用$sort运算符进行排序,插入评论后,再按照评论时间降序排序 public void demoStep1() { Query query = query(where("username").is("lison")); Comment comment = new Comment(); comment.setAuthor("cang"); comment.setCommentTime(new Date()); comment.setContent("lison是我的粉丝"); Update update = new Update(); PushOperatorBuilder pob = update.push("comments"); pob.each(comment); pob.sort(new Sort(new Sort.Order(Direction.DESC, "commentTime"))); System.out.println("---------------"); WriteResult updateFirst = tempelate.updateFirst(query, update,User.class); System.out.println("---------------"); System.out.println(updateFirst.getN()); } @Test // 查看人员时加载最新的三条评论; // db.users.find({"username":"lison"},{"comments":{"$slice":[0,3]}}).pretty() public void demoStep2() { //{"username":"lison"} Query query = query(where("username").is("lison")); //{"comments":{"$slice":[0,3]} query.fields().include("comments").slice("comments", 0, 3); System.out.println("---------------"); List<User> find = tempelate.find(query, User.class); System.out.println("---------------"); System.out.println(find); } @Test // 点击评论的下一页按钮,新加载三条评论 // db.users.find({"username":"lison"},{"comments":{"$slice":[3,3]},"$id":1}).pretty(); public void demoStep3() { Query query = query(where("username").is("lison")); query.fields().include("comments").slice("comments", 3, 3) .include("id"); System.out.println("---------------"); List<User> find = tempelate.find(query, User.class); System.out.println("---------------"); System.out.println(find); } /** * db.users.aggregate([{"$match":{"username":"lison"}}, {"$unwind":"$comments"}, {$sort:{"comments.commentTime":-1}}, {"$project":{"comments":1}}, {"$skip":6}, {"$limit":3}]) */ // 如果有多种排序需求怎么处理,使用聚合 @Test public void demoStep4() { Aggregation aggs = newAggregation( match(where("username").is("lison")), unwind("comments"), sort(Direction.ASC, "comments.commentTime"), project("comments"), skip(6), limit(3)); System.out.println("---------------"); AggregationResults<Object> aggregate = tempelate.aggregate(aggs, "users", Object.class); System.out.println("---------------"); List<Object> mappedResults = aggregate.getMappedResults(); System.out.println(mappedResults.size()); } }
MongoDB连接池配置
聚合的理解
聚合框架就是定义一个管道,管道里的每一步都为下一步输出数据数据
常用的管道操作符
$project:投影,指定输出文档中的字段;
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$group操作符
$group:可以分组的数据执行如下的表达式计算:
$sum:计算总和。
$avg:计算平均值。
$min:根据分组,获取集合中所有文档对应值得最小值。
$max:根据分组,获取集合中所有文档对应值得最大值。
聚合训练
查询2015年4月3号之前,每个用户每个月消费的总金额,并按用户名进行排序:
db.orders.aggregate([
{"$match":{ "orderTime" : { "$lt" : new Date("2015-04-03T16:00:00.000Z")}}},
{"$group":{"_id":{"useCode":"$useCode","month":{"$month":"$orderTime"}},"total":{"$sum":"$price"}}},
{"$sort":{"_id":1}}
])
package com.enjoylearning.mongo.entity; import java.math.BigDecimal; import java.util.Date; import org.bson.types.ObjectId; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "orders") public class Order { @Id private String id; private String orderCode; private String useCode; private Date orderTime; private BigDecimal price; private String[] Auditors; public String getOrderCode() { return orderCode; } public void setOrderCode(String orderCode) { this.orderCode = orderCode; } public Date getOrderTime() { return orderTime; } public void setOrderTime(Date orderTime) { this.orderTime = orderTime; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUseCode() { return useCode; } public void setUseCode(String useCode) { this.useCode = useCode; } public String[] getAuditors() { return Auditors; } public void setAuditors(String[] auditors) { Auditors = auditors; } }
package com.enjoylearning.lison.mongodb; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Random; import java.util.UUID; import javax.annotation.Resource; import org.bson.types.ObjectId; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.FindAndModifyOptions; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update.PushOperatorBuilder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.enjoylearning.mongo.entity.Comment; import com.enjoylearning.mongo.entity.MyOrder; import com.enjoylearning.mongo.entity.Order; import com.enjoylearning.mongo.entity.User; import com.mongodb.WriteResult; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class GenarateOrdersTest { private static final Logger logger = LoggerFactory.getLogger(GenarateOrdersTest.class); @Resource private MongoOperations tempelate; //随机生成orderTest数据 @Test public void batchInsertOrder() { String[] userCodes = new String[] { "james", "AV", "allen", "six", "peter", "mark", "king", "zero", "lance", "deer", "lison" }; String[] auditors = new String[] { "auditor1","auditor2","auditor3","auditor4","auditor5"}; List<Order> list = new ArrayList<Order>(); Random rand = new Random(); for (int i = 0; i < 100000; i++) { Order order = new Order(); int num = rand.nextInt(11); order.setUseCode(userCodes[num]); order.setOrderCode(UUID.randomUUID().toString()); order.setOrderTime(RondomDateTest.randomDate("2015-01-01","2017-10-31")); order.setPrice(RondomDateTest.randomBigDecimal(10000, 1)); int length = rand.nextInt(5)+1; String[] temp = new String[length]; for (int j = 0; j < temp.length; j++) { temp[j] = getFromArrays(temp,auditors,rand); } order.setAuditors(temp); list.add(order); } tempelate.insertAll(list); } private String getFromArrays(String[] temp, String[] auditors, Random rand) { String ret = null; boolean test = true; while (test) { ret = auditors[rand.nextInt(5)]; int i =0; for (String _temp : temp) { i++; if(ret.equals(_temp)){ break; } } if(i==temp.length){ test=false; } } return ret; } }
查询2015年4月3号之前,每个审核员分别审批的订单总金额,按审核员名称进行排序:
db.orders.aggregate([{"$match":{ "orderTime" : { "$lt" : new Date("2015-04-03T16:00:00.000Z")}}},
{"$unwind":"$Auditors"},
{"$group":{"_id":{"Auditors":"$Auditors"},"total":{"$sum":"$price"}}},
{"$sort":{"_id":1}}])
三、更新
新增操作
insertOne:插入单个文档
insertMany:插入多个文档
如果数据库和集合不存在,insert操作将自动创建;
对于插入的数据,mongoDB自动生成 ObjectId 作为_id 字段(物理主键)
删除操作
deleteOne(query):删除单个文档
deleteMany(query):删除多个文档
删除操作是不会删除索引的,就算你把数据全部删除;
更新操作概要
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
参数说明:
query : update的查询条件,类似sql update查询内where后面的;
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,写策略配置。
upsert实例
db.users.update({"username":"cang"},{"$set":{"age":18}},{"upsert":true})
数据不存在,记录将被插入
与插入操作相比,upsert插入的结果返回了_id字段
更新选择器
更新示例
删除字段示例
db.users.updateMany({"username":"lison"},{"$unset":{"country":"","age":""}})
更新字段名称示例
db.users.updateMany({"username":"lison"},{"$rename":{"lenght":"height", "username":"name"}})
$each作用示例
db.users.updateMany({ "username" : "james"}, { "$addToSet" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}})
db.users.updateMany({ "username" : "james"}, { "$addToSet" : { "favorites.movies" : { "$each" : [ "小电影2 " , "小电影3"]}}})
删除字符串数组中元素示例
db.users.updateMany({ "username" : "james"}, { "$pull" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}})
db.users.updateMany({ "username" : "james"}, { "$pullAll" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}})
向对象数组中插入元素
给james老师增加一条评论($push,默认放在数组最后)
db.users.updateOne({"username":"james"},{"$push":{"comments":{"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-01-06T00:00:00")}}})
给james老师批量新增两条评论($push,$each)
db.users.updateOne({"username":"james"},
{"$push":{"comments":
{"$each":[{"author":"lison22","content":"yyyytttt","commentTime":ISODate("2019-02-06T00:00:00")},
{"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-03-06T00:00:00")}]}}})
给james老师批量新增两条评论并对数组进行排序($push,$each,$sort)
db.users.updateOne({"username":"james"},
{"$push": {"comments":
{"$each":[ {"author":"lison22","content":"yyyytttt","commentTime":ISODate("2019-04-06T00:00:00")},
{"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-05-06T00:00:00")} ],
$sort: {"commentTime":-1} } } })
删除对象数组中元素示
删除lison22对james的所有评论 (批量删除)
db.users.update({"username":"james"},
{"$pull":{"comments":{"author":"lison22"}}})
删除lison5对lison评语为"lison是苍老师的小迷弟"的评论
db.users.update({"username":"lison"},
{"$pull":{"comments":{"author":"lison5",
"content":"lison是苍老师的小迷弟"}}})
更新对象数组中元素,$符号示例
db.users.updateMany({"username":"james","comments.author":"lison1"},
{“$set”:{“comments.$.content":"xxoo",
"comments.$.author":"lison10" }})
含义:精确修改某人某一条精确的评论,如果有多个符合条件的数据,则修改第一条数据。无法批量修改数组元素,也无法对数组元素做批量更新
更新的注意点
mongodb的更新都是原子的,mongodb所有的写操作都是有锁的。mongoDB 2.2之前锁级别为实例级别,mongoDB 2.2到3.2之前的版本锁级别为数据库级别,mongoDB 3.2以后,WiredTiger的锁级别是文档级别;
findAndModify命令:在同一往返过程中原子更新文档并返回它;
findandModify命令示例
常规的update的方法不能返回更新后的数据
db.fam.update({"name":"morris1"},{"$inc":{"age":1}})
使用findandModify方法在修改数据同时返回更新前的数据或更新后的数据
db.fam.findAndModify({query:{name:'morris1'},
update:{$inc:{age:1}},
'new':true});
Java示例代码
原生驱动的实现
package com.enjoylearning.lison.mongodb; import static com.mongodb.client.model.Filters.*; import static com.mongodb.client.model.Projections.*; import static com.mongodb.client.model.Sorts.*; import static com.mongodb.client.model.Aggregates.*; import static com.mongodb.client.model.Updates.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.bson.BSON; import org.bson.BsonDocument; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.codecs.pojo.PojoCodecProvider; import org.bson.conversions.Bson; import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.mongodb.Block; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; import com.mongodb.client.AggregateIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import com.mongodb.client.model.FindOneAndUpdateOptions; import com.mongodb.client.model.Projections; import com.mongodb.client.model.PushOptions; import com.mongodb.client.model.ReturnDocument; import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.model.Updates; import com.mongodb.client.result.UpdateResult; import com.mongodb.operation.OrderBy; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class JavaUpdateObjArray { private static final Logger logger = LoggerFactory.getLogger(JavaUpdateObjArray.class); private MongoDatabase db; private MongoCollection<Document> collection; @Resource(name="mongo") private MongoClient client; @Before public void init(){ db = client.getDatabase("lison"); collection=db.getCollection("users"); } //--------------------------------------upsert demo-------------------------------------------------------------- //测试upsert //db.users.update({"username":"cang"},{"$set":{"age":18}},{"upsert":true}) @Test public void upsertTest(){ Bson filter = eq("username","cang"); Bson update = set("age", 18); UpdateOptions upsert = new UpdateOptions().upsert(true); UpdateResult updateOne = collection.updateOne(filter, update,upsert); System.out.println(updateOne.getModifiedCount()); System.out.println(updateOne.getUpsertedId()); } //测试unset,删除字段示例 //db.users.updateMany({"username":"lison"},{"$unset":{"country":"","age":""}}) @Test public void unsetTest(){ Bson filter = eq("username","lison"); Bson country = unset("country"); Bson age = unset("age"); Bson update = combine(country,age); UpdateResult updateOne = collection.updateMany(filter, update); System.out.println(updateOne.getModifiedCount()); System.out.println(updateOne.getUpsertedId()); } //测试rename,更新字段名称示例 //db.users.updateMany({"username":"lison"},{"$rename":{"lenght":"height", "username":"name"}}) @Test public void renameTest(){ Bson filter = eq("username","lison"); Bson rename1 = rename("lenght", "height"); Bson rename2 = rename("username", "name"); Bson update = combine(rename1,rename2); UpdateResult updateOne = collection.updateMany(filter, update); System.out.println(updateOne.getModifiedCount()); System.out.println(updateOne.getUpsertedId()); } //测试pull pullAll,删除字符串数组中元素示例 // db.users.updateMany({ "username" : "james"}, { "$pull" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}}) // db.users.updateMany({ "username" : "james"}, { "$pullAll" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}}) @Test public void pullAllTest(){ Bson filter = eq("username","james"); Bson pull = pull("favorites.movies", Arrays.asList("小电影2 " , "小电影3")); UpdateResult updateOne = collection.updateMany(filter, pull); System.out.println(updateOne.getModifiedCount()); System.out.println(updateOne.getUpsertedId()); Bson pullAll = pullAll("favorites.movies", Arrays.asList("小电影2 " , "小电影3")); updateOne = collection.updateMany(filter, pullAll); System.out.println(updateOne.getModifiedCount()); System.out.println(updateOne.getUpsertedId()); } //--------------------------------------insert demo-------------------------------------------------------------- //给james老师增加一条评论($push) //db.users.updateOne({"username":"james"}, // {"$push":{"comments":{"author":"lison23", // "content":"ydddyyytttt", // "commentTime":ISODate("2019-01-06T00:00:00")}}}) @Test public void addOneComment(){ Document comment = new Document().append("author", "lison23") .append("content", "ydddyyytttt") .append("commentTime", getDate("2019-01-06")); Bson filter = eq("username","james"); Bson update = push("comments",comment); UpdateResult updateOne = collection.updateOne(filter, update); System.out.println(updateOne.getModifiedCount()); } // 给james老师批量新增两条评论($push,$each) // db.users.updateOne({"username":"james"}, // {"$push":{"comments": // {"$each":[{"author":"lison22","content":"yyyytttt","commentTime":ISODate("2019-02-06T00:00:00")}, // {"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-03-06T00:00:00")}]}}}) @Test public void addManyComment(){ Document comment1 = new Document().append("author", "lison33") .append("content", "lison33lison33") .append("commentTime", getDate("2019-02-06")); Document comment2 = new Document().append("author", "lison44") .append("content", "lison44lison44") .append("commentTime", getDate("2019-03-06")); Bson filter = eq("username","james"); Bson pushEach = pushEach("comments",Arrays.asList(comment1,comment2)); UpdateResult updateOne = collection.updateOne(filter, pushEach); System.out.println(updateOne.getModifiedCount()); } // 给james老师批量新增两条评论并对数组进行排序($push,$eachm,$sort) // db.users.updateOne({"username":"james"}, // {"$push": {"comments": // {"$each":[ {"author":"lison22","content":"yyyytttt","commentTime":ISODate("2019-04-06T00:00:00")}, // {"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-05-06T00:00:00")} ], // $sort: {"commentTime":-1} } } }) @Test public void addManySortComment(){ Document comment1 = new Document().append("author", "lison00") .append("content", "lison00lison00") .append("commentTime", getDate("2019-04-06")); Document comment2 = new Document().append("author", "lison01") .append("content", "lison01lison01") .append("commentTime", getDate("2019-05-06")); Bson filter = eq("username","james"); Document sortDoc = new Document().append("commentTime", -1); PushOptions pushOption = new PushOptions().sortDocument(sortDoc); Bson pushEach = pushEach("comments",Arrays.asList(comment1,comment2),pushOption); UpdateResult updateOne = collection.updateOne(filter, pushEach); System.out.println(updateOne.getModifiedCount()); } //--------------------------------------delete demo-------------------------------------------------------------- // 删除lison1对james的所有评论 (批量删除) // db.users.update({"username":“james"}, // {"$pull":{"comments":{"author":"lison33"}}}) @Test public void deleteByAuthorComment(){ Document comment = new Document().append("author", "lison33"); Bson filter = eq("username","james"); Bson update = pull("comments",comment); UpdateResult updateOne = collection.updateOne(filter, update); System.out.println(updateOne.getModifiedCount()); } // 删除lison5对lison评语为“lison是苍老师的小迷弟”的评论(精确删除) // db.users.update({"username":"lison"}, // {"$pull":{"comments":{"author":"lison5", // "content":"lison是苍老师的小迷弟"}}}) @Test public void deleteByAuthorContentComment(){ Document comment = new Document().append("author", "lison5") .append("content", "lison是苍老师的小迷弟"); Bson filter = eq("username","lison"); Bson update = pull("comments",comment); UpdateResult updateOne = collection.updateOne(filter, update); System.out.println(updateOne.getModifiedCount()); } //--------------------------------------update demo-------------------------------------------------------------- // db.users.updateMany({"username":"james","comments.author":"lison01"}, // {"$set":{"comments.$.content":"xxoo", // "comments.$.author":"lison10" }}) // 含义:精确修改某人某一条精确的评论,如果有多个符合条件的数据,则修改最后一条数据。无法批量修改数组元素 @Test public void updateOneComment(){ Bson filter = and(eq("username","james"),eq("comments.author","lison01")); Bson updateContent = set("comments.$.content","xxoo"); Bson updateAuthor = set("comments.$.author","lison10"); Bson update = combine(updateContent,updateAuthor); UpdateResult updateOne = collection.updateOne(filter, update); System.out.println(updateOne.getModifiedCount()); } //--------------------------------------findandModify demo-------------------------------------------------------------- //使用findandModify方法在修改数据同时返回更新前的数据或更新后的数据 //db.fam.findAndModify({query:{name:'morris1'}, // update:{$inc:{age:1}}, // 'new':true}); @Test public void findAndModifyTest(){ Bson filter = eq("name","morris1"); Bson update = inc("age",1); // //实例化findAndModify的配置选项 FindOneAndUpdateOptions fauo = new FindOneAndUpdateOptions(); // //配置"new":true fauo.returnDocument(ReturnDocument.AFTER);// MongoCollection<Document> numCollection = db.getCollection("fam"); Document ret = numCollection.findOneAndUpdate(filter, update,fauo); System.out.println(ret.toJson()); } private Date getDate(String string) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date parse=null; try { parse = sdf.parse(string); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return parse; } }
Spring data的实现
package com.enjoylearning.lison.mongodb; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import javax.annotation.Resource; import org.bson.types.ObjectId; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.FindAndModifyOptions; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update.PushOperatorBuilder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.enjoylearning.mongo.entity.Comment; import com.enjoylearning.mongo.entity.Doc; import com.enjoylearning.mongo.entity.MyOrder; import com.enjoylearning.mongo.entity.User; import com.mongodb.WriteResult; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringUpdateObjArray { private static final Logger logger = LoggerFactory.getLogger(SpringUpdateObjArray.class); @Resource private MongoOperations tempelate; //--------------------------------------upsert demo-------------------------------------------------------------- //测试upsert //db.users.update({"username":"cang"},{"$set":{"age":18}},{"upsert":true}) @Test public void upsertTest(){ Query query = query(Criteria.where("username").is("cang")); Update set = new Update().set("age", 18); WriteResult upsert = tempelate.upsert(query, set, User.class); System.out.println(upsert.getN()); System.out.println(upsert.getUpsertedId()); } //测试unset,删除字段示例 //db.users.updateMany({"username":"lison"},{"$unset":{"country":"","age":""}}) @Test public void unsetTest(){ Query query = query(Criteria.where("username").is("lison")); Update unset = new Update().unset("country").unset("age"); WriteResult upsert = tempelate.updateMulti(query, unset, User.class); System.out.println(upsert.getN()); } //测试rename,更新字段名称示例 //db.users.updateMany({"username":"lison"},{"$rename":{"lenght":"height", "username":"name"}}) @Test public void renameTest(){ Query query = query(Criteria.where("username").is("lison")); Update rename = new Update().rename("lenght", "height").rename("username", "name"); WriteResult upsert = tempelate.updateMulti(query, rename, User.class); System.out.println(upsert.getN()); } //测试pull pullAll,删除字符串数组中元素示例 // db.users.updateMany({ "username" : "james"}, { "$pull" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}}) // db.users.updateMany({ "username" : "james"}, { "$pullAll" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}}) @Test public void pullAllTest(){ Query query = query(Criteria.where("username").is("james")); Update pull = new Update().pull("favorites.movies", Arrays.asList("小电影2 " , "小电影3")); WriteResult upsert = tempelate.updateMulti(query, pull, User.class); System.out.println(upsert.getN()); query = query(Criteria.where("username").is("james")); Update pullAll = new Update().pullAll("favorites.movies", new String[]{"小电影2 " , "小电影3"}); upsert = tempelate.updateMulti(query, pullAll, User.class); System.out.println(upsert.getN()); } //--------------------------------------insert demo-------------------------------------------------------------- //给james老师增加一条评论($push) //db.users.updateOne({"username":"james"}, // {"$push":{"comments":{"author":"lison23", // "content":"ydddyyytttt", // "commentTime":ISODate("2019-01-06T00:00:00")}}}) @Test public void addOneComment(){ Query query = query(Criteria.where("username").is("james")); Comment comment = new Comment(); comment.setAuthor("lison23"); comment.setContent("ydddyyytttt"); comment.setCommentTime(getDate("2019-01-06")); Update push = new Update().push("comments", comment); WriteResult updateFirst = tempelate.updateFirst(query, push, User.class); System.out.println(updateFirst.getN()); } // 给james老师批量新增两条评论($push,$each) // db.users.updateOne({"username":"james"}, // {"$push":{"comments": // {"$each":[{"author":"lison22","content":"yyyytttt","commentTime":ISODate("2019-02-06T00:00:00")}, // {"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-03-06T00:00:00")}]}}}) @Test public void addManyComment(){ Query query = query(Criteria.where("username").is("james")); Comment comment1 = new Comment(); comment1.setAuthor("lison55"); comment1.setContent("lison55lison55"); comment1.setCommentTime(getDate("2019-02-06")); Comment comment2 = new Comment(); comment2.setAuthor("lison66"); comment2.setContent("lison66lison66"); comment2.setCommentTime(getDate("2019-03-06")); Update push = new Update().pushAll("comments", new Comment[]{comment1,comment2}); WriteResult updateFirst = tempelate.updateFirst(query, push, User.class); System.out.println(updateFirst.getN()); } // 给james老师批量新增两条评论并对数组进行排序($push,$eachm,$sort) // db.users.updateOne({"username":"james"}, // {"$push": {"comments": // {"$each":[ {"author":"lison22","content":"yyyytttt","commentTime":ISODate("2019-04-06T00:00:00")}, // {"author":"lison23","content":"ydddyyytttt","commentTime":ISODate("2019-05-06T00:00:00")} ], // $sort: {"commentTime":-1} } } }) @Test public void addManySortComment(){ Query query = query(Criteria.where("username").is("james")); Comment comment1 = new Comment(); comment1.setAuthor("lison77"); comment1.setContent("lison55lison55"); comment1.setCommentTime(getDate("2019-04-06")); Comment comment2 = new Comment(); comment2.setAuthor("lison88"); comment2.setContent("lison66lison66"); comment2.setCommentTime(getDate("2019-05-06")); Update update = new Update(); PushOperatorBuilder pob = update.push("comments"); pob.each(comment1,comment2); pob.sort(new Sort(new Sort.Order(Direction.DESC, "commentTime"))); System.out.println("---------------"); WriteResult updateFirst = tempelate.updateFirst(query, update,User.class); System.out.println(updateFirst.getN()); } //--------------------------------------delete demo-------------------------------------------------------------- // 删除lison1对james的所有评论 (批量删除) // db.users.update({"username":“james"}, // {"$pull":{"comments":{"author":"lison23"}}}) @Test public void deleteByAuthorComment(){ Query query = query(Criteria.where("username").is("james")); Comment comment1 = new Comment(); comment1.setAuthor("lison55"); Update pull = new Update().pull("comments",comment1); WriteResult updateFirst = tempelate.updateFirst(query, pull, User.class); System.out.println(updateFirst.getN()); } // 删除lison5对lison评语为“lison是苍老师的小迷弟”的评论(精确删除) // db.users.update({"username":"lison"}, // {"$pull":{"comments":{"author":"lison5", // "content":"lison是苍老师的小迷弟"}}}) @Test public void deleteByAuthorContentComment(){ Query query = query(Criteria.where("username").is("lison")); Comment comment1 = new Comment(); comment1.setAuthor("lison5"); comment1.setContent("lison是苍老师的小迷弟"); Update pull = new Update().pull("comments",comment1); WriteResult updateFirst = tempelate.updateFirst(query, pull, User.class); System.out.println(updateFirst.getN()); } //--------------------------------------update demo-------------------------------------------------------------- // db.users.updateMany({"username":"james","comments.author":"lison1"}, // {"$set":{"comments.$.content":"xxoo", // "comments.$.author":"lison10" }}) // 含义:精确修改某人某一条精确的评论,如果有多个符合条件的数据,则修改最后一条数据。无法批量修改数组元素 @Test public void updateOneComment(){ Query query = query(where("username").is("lison").and("comments.author").is("lison4")); Update update = update("comments.$.content","xxoo").set("comments.$.author","lison11"); WriteResult updateFirst = tempelate.updateFirst(query, update, User.class); System.out.println(updateFirst.getN()); } //--------------------------------------findandModify demo-------------------------------------------------------------- //使用findandModify方法在修改数据同时返回更新前的数据或更新后的数据 //db.fam.findAndModify({query:{name:'morris1'}, // update:{$inc:{age:1}}, // 'new':true}); @Test public void findAndModifyTest(){ Query query = query(where("name").is("morris1")); Update update = new Update().inc("age", 1); FindAndModifyOptions famo = FindAndModifyOptions.options().returnNew(true); Doc doc = tempelate.findAndModify(query, update,famo, Doc.class); System.out.println(doc.toString()); } private Date getDate(String string) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date parse=null; try { parse = sdf.parse(string); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return parse; } }
四、其他命令
其他常用命令
show dbs :显示数据库列表
show collections :显示集合列表
db : 显示当前数据库
db.stats() :显示数据库信息
db.serverStatus() : 查看服务器状态
db.dropDatabase():删除数据库
db.help(),db.collection.help():内置帮助,显示各种方法的说明;
db.users.find().size():获取查询集合的数量;
db.users.drop():删除集合;