SpringBoot 整合 MongoDB 實戰解說

一、介紹

在前面的文章中,我們詳細的介紹了 MongoDB 的配置和使用,如果你對 MongoDB 還不是很了解,也沒關係,在 MongoDB 中有三個比較重要的名詞:數據庫、集合、文檔

  • 數據庫(Database):和關係型數據庫一樣,每個數據庫中有自己的用戶權限,不同的項目組可以使用不同的數據庫
  • 集合(Collection): 集合指的是文檔組(類似於 Mysql 中的表的概念),裏面可以存儲許多文檔
  • 文檔(Document): 文檔是 MongoDB 中最基本的數據單元,由鍵值對組成,類似於 JSON 格式,可以存儲不同字段,字段的值可以包括其他文檔、數組和文檔數組

搞懂這三個名詞,基本就可以上手了,今天我們以 Java 語言為例,詳細的介紹 Java 客戶端改如何操作 MongoDB !

話不多說,直接開擼!

二、Java 客戶端

2.1、MongoDB 連接

Java 連接 MongoDB 服務器,與我們常用的連接關係型數據庫方式類似!

標準 URI 連接語法:

mongodb://username:password@host1:port1,host2:port2,...,hostN:portN/database?options

參數說明:

  • mongodb://:這是固定的格式,必須要指定
  • username:password@:可選項,如果設置,在連接數據庫服務器之後,驅動都會嘗試登錄這個數據庫
  • host1:port1:主機IP和端口號,必須指定至少一個host。如果要連接複製集,請指定多個主機地址
  • /database:如果指定了username:password@,連接時會驗證並登錄指定數據庫。若不指定,默認打開 test 數據庫
  • ?options:連接可選項,例如connectTimeoutMS=5000ms,表示連接等待時間最長 5 秒

例如,無密碼連接 MongoDB

mongodb://127.0.0.1:27017

使用用戶名test,密碼test登錄 MongoDB 的test_db數據庫

mongodb://test:[email protected]:27017/test_db

無密碼連接指定三台服務器 (端口 27017, 27018, 和27019)

mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019

2.2、添加依賴包

和關係型數據庫操作一樣,在 Java 程序中如果要使用 MongoDB,先要添加對應的 MongoDB JDBC 驅動器,然後才能繼續操作!

在選擇的版本號的時候,注意需要和服務器中的安裝版本匹配,具體的版本號選擇可以從如下地址中獲取到最新的版本:mongo-java-driver

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.7</version>
</dependency>

2.3、連接數據庫

連接數據庫的 Java 代碼如下:

private static MongoClient mongoClient;

static {
    try {
        //連接到MongoDB服務 如果是遠程連接可以替換「localhost」為服務器所在IP地址
        mongoClient = MongoClients.create("mongodb://test:[email protected]:27017/test_db");
        System.out.println("Connect to database successfully");
    } catch (Exception e) {
        System.err.println( e.getClass().getName() + ": " + e.getMessage() );
    }
}

上文中採用的是用戶名和密碼方式登錄數據庫,因為數據庫已經開啟了權限驗證,因此需要通過用戶名和密碼才能登錄。

2.4、創建集合

com.mongodb.client包裏面都幫我們集成好了大部分常用的 api,我們可以通過MongoDatabase類中的createCollection()方法來創建集合。

創建一個tb_role集合,代碼片段如下:

/**
 * 創建集合
 * @param args
 */
public static void main(String[] args) {
    // 連接到數據庫
    MongoDatabase mongoDatabase = mongoClient.getDatabase("test_db");
    System.out.println("Connect to database successfully");
    mongoDatabase.createCollection("tb_role");
    System.out.println("集合創建成功");
}

如果想刪除集合,操作也很簡單!

/**
 * 刪除集合
 * @param args
 */
public static void main(String[] args) {
    // 連接到數據庫
    MongoDatabase mongoDatabase = mongoClient.getDatabase("test_db");
    System.out.println("Connect to database successfully");
    mongoDatabase.getCollection("tb_role").drop();
    System.out.println("集合 tb_role 刪除成功");
}

2.5、創建文檔

我們可以通過MongoCollection類中的insertMany()方法來插入一個文檔。

tb_role集合中插入文檔,代碼片段如下:

/**
 * 插入文檔
 * @param args
 */
public static void main(String[] args) {
    // 連接到數據庫
    MongoDatabase mongoDatabase = mongoClient.getDatabase("test_db");
    System.out.println("Connect to database successfully");
    //獲取集合
    MongoCollection<Document> collection = mongoDatabase.getCollection("tb_role");

    //向集合中插入文檔
    Document document = new Document("name", "管理員").
            append("code", "manager").
            append("sort", 100);
    List<Document> documents = new ArrayList<>();
    documents.add(document);
    collection.insertMany(documents);
    System.out.println("文檔插入成功");
}

2.6、更新文檔

我們可以通過MongoCollection類中的updateMany()方法來更新集合中的文檔。

更新tb_role集合中的指定文檔信息,代碼片段如下:

/**
 * 更新文檔
 * @param args
 */
public static void main(String[] args) {
    // 連接到數據庫
    MongoDatabase mongoDatabase = mongoClient.getDatabase("test_db");
    System.out.println("Connect to database successfully");
    //獲取集合
    MongoCollection<Document> collection = mongoDatabase.getCollection("tb_role");

    //更新文檔
    collection.updateMany(Filters.eq("code", "manager"), new Document("$set",new Document("name","經理")));

    //遍歷所有文檔
    FindIterable<Document> findIterable = collection.find();
    MongoCursor<Document> mongoCursor = findIterable.iterator();
    while(mongoCursor.hasNext()){
        System.out.println(mongoCursor.next());
    }
}

上文操作類似於 SQL語句中的update tb_role set name = '經理' where code = 'manager'

2.7、刪除文檔

我們可以通過MongoCollection類中的deleteOne()或者deleteMany方法來刪除集合中的文檔。

刪除tb_role集合中的指定文檔信息,代碼片段如下:

/**
 * 刪除文檔
 * @param args
 */
public static void main(String[] args) {
    // 連接到數據庫
    MongoDatabase mongoDatabase = mongoClient.getDatabase("test_db");
    System.out.println("Connect to database successfully");
    //獲取集合
    MongoCollection<Document> collection = mongoDatabase.getCollection("tb_role");

    //刪除符合條件的第一個文檔
    collection.deleteOne(Filters.eq("code", "manager"));
    //刪除所有符合條件的文檔
    collection.deleteMany (Filters.eq("code", "manager"));

    //遍歷所有文檔
    FindIterable<Document> findIterable = collection.find();
    MongoCursor<Document> mongoCursor = findIterable.iterator();
    while(mongoCursor.hasNext()){
        System.out.println(mongoCursor.next());
    }
}

在這裡需要注意一下,在刪除的時候,官方推薦儘可能先查詢一下這個數據是否存在,如果存在,然後在執行刪除操作,可以調用findOneAndDelete()方法進行刪除!

2.8、查詢文檔

MongoCollection類中提供了非常豐富的檢索文檔的方法,例如,我們可以通過find()方法來獲取集合中的所有文檔。

檢索tb_role集合中的文檔信息,代碼片段如下:

/**
 * 查詢文檔
 * @param args
 */
public static void main(String[] args) {
    // 連接到數據庫
    MongoDatabase mongoDatabase = mongoClient.getDatabase("test_db");
    System.out.println("Connect to database successfully");
    //獲取集合
    MongoCollection<Document> collection = mongoDatabase.getCollection("tb_role");

    //遍歷所有文檔
    FindIterable<Document> findIterable = collection.find();
    MongoCursor<Document> mongoCursor = findIterable.iterator();
    while(mongoCursor.hasNext()){
        System.out.println(mongoCursor.next());
    }

    //查詢當前集合所有文檔數量
    long count = collection.countDocuments();
    System.out.println("當前文檔數量:" + count);

    //帶條件遍歷文檔
    FindIterable<Document> documentFindIterable = collection.find(Filters.eq("code", "manager"));
    MongoCursor<Document> documentMongoCursor = documentFindIterable.iterator();
    while(documentMongoCursor.hasNext()){
        System.out.println(documentMongoCursor.next());
    }
}

三、SpringBoot 整合 MongoDB

採用 SpringBoot 來對接 MongoDB,可以說極其簡單,下面就以常用的幾個操作為例來介紹,過程如下!

3.1、創建 SpringBoot 工程,添加 MongoDB 依賴包

<!-- 引入springboot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.0.RELEASE</version>
</parent>

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

3.2、添加配置文件

application.properties文件中添加mongodb配置

#配置數據庫連接地址
spring.data.mongodb.uri=mongodb://test123:[email protected]:27017/test_db

3.3、創建實體類

創建用於示例中測試的實體類Person

其中註解@Document(collection="persons")用於指定當前文檔屬於集合persons

註解@Id表示當前id字段屬於主鍵類型。

/**
 * 使用@Document註解指定集合名稱
 */
@Document(collection="persons")
public class Person implements Serializable {
    private static final long serialVersionUID = -3258839839160856613L;

    /**
     * 使用@Id註解指定MongoDB中的 _id 主鍵
     */
    @Id
    private Long id;

    private String userName;

    private String passWord;

    private Integer age;

    private Date createTime;

    //...get/set

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", passWord='" + passWord + '\'' +
                ", age=" + age +
                ", createTime=" + createTime +
                '}';
    }
}

3.4、操作 MongoDB

Springboot 操作 MongoDB 有兩種方式。

  • 第一種方式是採用 Springboot 官方推薦的 JPA 方式,這種操作方式,使用簡單但是靈活性比較差。

  • 第二種方式是採用 Spring Data MongoDB 封裝的 MongoDB 官方 Java 驅動 MongoTemplate 對 MongoDB 進行操作,這種方式非常靈活,能滿足絕大部分需求。

本文將採用第二種方式進行介紹!

3.5、插入文檔

MongoTemplate提供了insert()方法,用於插入文檔,示例代碼如下:

  • 用於插入文檔

沒指定集合名稱時,會取@Document註解中的集合名稱

@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 插入文檔
     * @throws Exception
     */
    @Test
    public void insert() throws Exception {
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());
        mongoTemplate.insert(person);
    }
}
  • 自定義集合名稱,插入文檔
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 自定義集合,插入文檔
     * @throws Exception
     */
    @Test
    public void insertCustomCollection() throws Exception {
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());
        mongoTemplate.insert(person, "custom_person");
    }
}
  • 自定義集合,批量插入文檔

如果採用批量插入文檔,必須指定集合名稱

@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 自定義集合,批量插入文檔
     * @throws Exception
     */
    @Test
    public void insertBatch() throws Exception {
        List<Person> personList = new ArrayList<>();
        Person person1 =new Person();
        person1.setId(10l);
        person1.setUserName("張三");
        person1.setPassWord("123456");
        person1.setCreateTime(new Date());
        personList.add(person1);

        Person person2 =new Person();
        person2.setId(11l);
        person2.setUserName("李四");
        person2.setPassWord("123456");
        person2.setCreateTime(new Date());
        personList.add(person2);

        mongoTemplate.insert(personList, "custom_person");
    }
}

3.6、存儲文檔

MongoTemplate提供了save()方法,用於存儲文檔。

在存儲文檔的時候會通過主鍵ID進行判斷,如果存在就更新,否則就插入,示例代碼如下:

  • 存儲文檔,如果沒有插入,否則通過主鍵ID更新
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 存儲文檔,如果沒有插入,否則更新
     * @throws Exception
     */
    @Test
    public void save() throws Exception {
        Person person =new Person();
        person.setId(13l);
        person.setUserName("八八");
        person.setPassWord("123456");
        person.setAge(40);
        person.setCreateTime(new Date());
        mongoTemplate.save(person);
    }
}
  • 自定義集合,存儲文檔
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 自定義集合,存儲文檔
     * @throws Exception
     */
    @Test
    public void saveCustomCollection() throws Exception {
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());
        mongoTemplate.save(person, "custom_person");
    }
}

3.7、更新文檔

MongoTemplate提供了updateFirst()updateMulti()方法,用於更新文檔,示例代碼如下:

  • 更新文檔,匹配查詢到的文檔數據中的第一條數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 更新文檔,匹配查詢到的文檔數據中的第一條數據
     * @throws Exception
     */
    @Test
    public void updateFirst() throws Exception {
        //更新對象
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三123");
        person.setPassWord("123456");
        person.setCreateTime(new Date());

        //更新條件
        Query query= new Query(Criteria.where("id").is(person.getId()));

        //更新值
        Update update= new Update().set("userName", person.getUserName()).set("passWord", person.getPassWord());
        //更新查詢滿足條件的文檔數據(第一條)
        UpdateResult result =mongoTemplate.updateFirst(query,update, Person.class);
        if(result!=null){
            System.out.println("更新條數:" + result.getMatchedCount());
        }
    }
}
  • 更新文檔,匹配查詢到的文檔數據中的所有數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 更新文檔,匹配查詢到的文檔數據中的所有數據
     * @throws Exception
     */
    @Test
    public void updateMany() throws Exception {
        //更新對象
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());

        //更新條件
        Query query= new Query(Criteria.where("id").is(person.getId()));

        //更新值
        Update update= new Update().set("userName", person.getUserName()).set("passWord", person.getPassWord());
        //更新查詢滿足條件的文檔數據(全部)
        UpdateResult result = mongoTemplate.updateMulti(query, update, Person.class);
        if(result!=null){
            System.out.println("更新條數:" + result.getMatchedCount());
        }
    }
}

3.8、刪除文檔

MongoTemplate提供了remove()findAndRemove()findAllAndRemove()方法,用於刪除文檔,示例代碼如下:

  • 刪除符合條件的所有文檔
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 刪除符合條件的所有文檔
     * @throws Exception
     */
    @Test
    public void remove() throws Exception {
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());

        Query query = new Query(Criteria.where("userName").is(person.getUserName()));
        DeleteResult result = mongoTemplate.remove(query, Person.class);
        System.out.println("刪除條數:" + result.getDeletedCount());
    }
}
  • 刪除符合條件的單個文檔,並返回刪除的文檔
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 刪除符合條件的單個文檔,並返回刪除的文檔
     * @throws Exception
     */
    @Test
    public void findAndRemove() throws Exception {
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());

        Query query = new Query(Criteria.where("id").is(person.getId()));
        Person result = mongoTemplate.findAndRemove(query, Person.class);
        System.out.println("刪除的文檔數據:" + result.toString());
    }
}
  • 刪除符合條件的所有文檔,並返回刪除的文檔
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 刪除符合條件的所有文檔,並返回刪除的文檔
     * @throws Exception
     */
    @Test
    public void findAllAndRemove() throws Exception {
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());

        Query query = new Query(Criteria.where("id").is(person.getId()));
        List<Person> result = mongoTemplate.findAllAndRemove(query, Person.class);
        System.out.println("刪除的文檔數據:" + result.toString());
    }
}

3.9、查詢文檔

MongoTemplate提供了非常多的文檔查詢方法,日常開發中用的最多的就是find()方法,示例代碼如下:

  • 查詢集合中的全部文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 查詢集合中的全部文檔數據
     * @throws Exception
     */
    @Test
    public void findAll() throws Exception {
        List<Person> result = mongoTemplate.findAll(Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 查詢集合中指定的ID文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 查詢集合中指定的ID文檔數據
     * @throws Exception
     */
    @Test
    public void findById() {
        long id = 1l;
        Person result = mongoTemplate.findById(id, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據條件查詢集合中符合條件的文檔,返回第一條數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據條件查詢集合中符合條件的文檔,返回第一條數據
     */
    @Test
    public void findOne() {
        String userName = "張三";
        Query query = new Query(Criteria.where("userName").is(userName));
        Person result = mongoTemplate.findOne(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據條件查詢集合中符合條件的文檔
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據條件查詢集合中符合條件的文檔
     */
    @Test
    public void findByCondition() {
        String userName = "張三";
        Query query = new Query(Criteria.where("userName").is(userName));
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據【AND】關聯多個查詢條件,查詢集合中的文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據【AND】關聯多個查詢條件,查詢集合中的文檔數據
     */
    @Test
    public void findByAndCondition() {
        // 創建條件
        Criteria criteriaUserName = Criteria.where("userName").is("張三");
        Criteria criteriaPassWord = Criteria.where("passWord").is("123456");
        // 創建條件對象,將上麵條件進行 AND 關聯
        Criteria criteria = new Criteria().andOperator(criteriaUserName, criteriaPassWord);
        // 創建查詢對象,然後將條件對象添加到其中
        Query query = new Query(criteria);
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據【OR】關聯多個查詢條件,查詢集合中的文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據【OR】關聯多個查詢條件,查詢集合中的文檔數據
     */
    @Test
    public void findByOrCondition() {
        // 創建條件
        Criteria criteriaUserName = Criteria.where("userName").is("張三");
        Criteria criteriaPassWord = Criteria.where("passWord").is("123456");
        // 創建條件對象,將上麵條件進行 OR 關聯
        Criteria criteria = new Criteria().orOperator(criteriaUserName, criteriaPassWord);
        // 創建查詢對象,然後將條件對象添加到其中
        Query query = new Query(criteria);
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據【IN】關聯多個查詢條件,查詢集合中的文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據【IN】關聯多個查詢條件,查詢集合中的文檔數據
     */
    @Test
    public void findByInCondition() {
        // 設置查詢條件參數
        List<Long> ids = Arrays.asList(1l, 10l, 11l);
        // 創建條件
        Criteria criteria = Criteria.where("id").in(ids);
        // 創建查詢對象,然後將條件對象添加到其中
        Query query = new Query(criteria);
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據【邏輯運算符】查詢集合中的文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據【邏輯運算符】查詢集合中的文檔數據
     */
    @Test
    public void findByOperator() {
        // 設置查詢條件參數
        int min = 20;
        int max = 35;
        Criteria criteria = Criteria.where("age").gt(min).lte(max);
        // 創建查詢對象,然後將條件對象添加到其中
        Query query = new Query(criteria);
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據【正則表達式】查詢集合中的文檔數據
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據【正則表達式】查詢集合中的文檔數據
     */
    @Test
    public void findByRegex() {
        // 設置查詢條件參數
        String regex = "^張*";
        Criteria criteria = Criteria.where("userName").regex(regex);
        // 創建查詢對象,然後將條件對象添加到其中
        Query query = new Query(criteria);
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據條件查詢集合中符合條件的文檔,獲取其文檔列表並排序
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 根據條件查詢集合中符合條件的文檔,獲取其文檔列表並排序
     */
    @Test
    public void findByConditionAndSort() {
        String userName = "張三";
        Query query = new Query(Criteria.where("userName").is(userName)).with(Sort.by("age"));
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 根據單個條件查詢集合中的文檔數據,並按指定字段進行排序與限制指定數目
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

   /**
     * 根據單個條件查詢集合中的文檔數據,並按指定字段進行排序與限制指定數目
     */
    @Test
    public void findByConditionAndSortLimit() {
        String userName = "張三";
        //從第一行開始,查詢2條數據返回
        Query query = new Query(Criteria.where("userName").is(userName)).with(Sort.by("createTime")).limit(2).skip(1);
        List<Person> result = mongoTemplate.find(query, Person.class);
        System.out.println("查詢結果:" + result.toString());
    }
}
  • 統計集合中符合【查詢條件】的文檔【數量】
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

   /**
     * 統計集合中符合【查詢條件】的文檔【數量】
     */
    @Test
    public void countNumber() {
        // 設置查詢條件參數
        String regex = "^張*";
        Criteria criteria = Criteria.where("userName").regex(regex);
        // 創建查詢對象,然後將條件對象添加到其中
        Query query = new Query(criteria);
        long count = mongoTemplate.count(query, Person.class);
        System.out.println("統計結果:" + count);
    }
}

4.0、創建索引

索引在所有的數據庫中,暫居的位置非常重要,例如當你檢索一張上百萬的數據表的時候,如果沒走索引,查詢效率會極其緩慢,對於 MongoDB 來說,同樣如此。

示例如下:

  • 創建升序索引
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 創建升序索引
     */
    @Test
    public void createAscendingIndex() {
        // 設置字段名稱
        String field = "userName";
        // 創建索引
        mongoTemplate.getCollection("persons").createIndex(Indexes.ascending(field));
    }
}
  • 移除索引
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

   /**
     * 根據索引名稱移除索引
     */
    @Test
    public void removeIndex() {
        // 設置字段名稱
        String field = "userName";
        // 刪除索引
        mongoTemplate.getCollection("persons").dropIndex(field);
    }
}
  • 查詢集合中所有的索引
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

    @Autowired
    private MongoTemplate mongoTemplate;

   /**
     * 查詢集合中所有的索引
     */
    @Test
    public void getIndexAll() {
        // 獲取集合中所有列表
        ListIndexesIterable<Document> indexList = mongoTemplate.getCollection("persons").listIndexes();
        // 獲取集合中全部索引信息
        for (Document document : indexList) {
            System.out.println("索引列表:" + document);
        }
    }
}
  • 我們還可以通過在實體類上加註解方式來創建索引
/**
 * 使用@Document註解指定集合名稱
 */
@Document(collection="persons")
public class Person implements Serializable {
    private static final long serialVersionUID = -3258839839160856613L;

    /**
     * 使用@Id註解指定MongoDB中的 _id 主鍵
     */
    @Id
    private Long id;

    private String userName;

    private String passWord;

    private Integer age;

    /**
     * 創建一個5秒之後文檔自動刪除的索引
     */
    @Indexed(expireAfterSeconds=5)
    private Date createTime;

    //...get/set

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", passWord='" + passWord + '\'' +
                ", age=" + age +
                ", createTime=" + createTime +
                '}';
    }
}

4.1、引入 MongoDB 中的事務

單節點 mongodb 不支持事務,需要搭建 MongoDB 複製集。

/**
 * 配置事務管理器
 *
 */
@Configuration
public class TransactionConfig {

    @Bean
    MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }

}

事務服務測試!

@Service
public class TransactionExample {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Transactional(rollbackFor = Exception.class)
    public Object transactionTest(){
        Person person =new Person();
        person.setId(1l);
        person.setUserName("張三");
        person.setPassWord("123456");
        person.setCreateTime(new Date());
        Person newPerson = mongoTemplate.insert(person);
        // 拋出異常,觀察數據是否進行回滾
        if(1 == 1){
            throw new RuntimeException("異常");
        }
        return newPerson;
    }
}

四、小結

本文主要圍繞 MongoDB 的 Java 客戶端使用進行基本的增刪改查操作介紹,在實際的業務場景中,可能還需要用到聚合函數等高級查詢,大家如果有這種需求,可以訪問如下地址獲取更加詳細的 api 文檔介紹:MongoDB 文檔查詢 api 介紹

五、參考

1、菜鳥教程 – mongodb

2、超級小豆丁 – MongoDB 介紹