mongodb

 

一、快速入门

数据结构介绍:人员信息

{
        "_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()));//打印受影响的行数
    }
    

    

    
    
    
    

}
View Code

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()));//打印受影响的行数
    }
    

    

    
    
    
    

}
View Code

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());
        
        
        
    }

    
        
    
    
    

}
View Code

开发框架版本选择

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);
    }




}
View Code

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>
View Code
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());

    }
    



}
View Code

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;
    }
    
    

}
View Code
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;

    }
    
    
}
View Code

查询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;
    }
  
  
  
}
View Code

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;
        }
      
    
    
}
View Code

 

四、其他命令

其他常用命令

show dbs :显示数据库列表
show collections :显示集合列表
db : 显示当前数据库
db.stats() :显示数据库信息
db.serverStatus() : 查看服务器状态
db.dropDatabase():删除数据库
db.help(),db.collection.help():内置帮助,显示各种方法的说明;
db.users.find().size():获取查询集合的数量;
db.users.drop():删除集合;

转载于:https://www.cnblogs.com/skorzeny/p/10473975.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值