1. 程式人生 > >springboot系列十一 Spring-Data-MongoDB

springboot系列十一 Spring-Data-MongoDB

mongodb

MongoDB 是一個基於分散式檔案儲存的NoSQL資料庫。由 C++ 語言編寫。旨在為 WEB 應用提供可擴充套件的高效能資料儲存解決方案。
MongoDB 是一個介於關係資料庫和非關係資料庫之間的產品,是非關係資料庫當中功能最豐富,最像關係資料庫的。

資料儲存格式類似於json

{ 
    "_id" : ObjectId("5c061052f94458c11e167a5a"), 
    "name" : "test", 
    "age" : NumberInt(13), 
    "createTime" : ISODate("2018-12-04T05:27:46.633+0000")
}

官方文件

https://docs.mongodb.com/manual/?_ga=2.34252649.996507481.1543901385-1321775126.1543901385

官方示例java程式碼

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

import java.util.ArrayList;
import java.util.List;

import com.mongodb.client.model.Indexes;

import static com.mongodb.client.model.Accumulators.sum;
import static com.mongodb.client.model.Aggregates.group;
import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Filters.eq;
import static java.util.Arrays.asList;

public class MongoDBExamples {

   public static void main(final String[] args) {

       // 1. Connect to MongoDB instance running on localhost
       MongoClient mongoClient = new MongoClient();

       // Access database named 'test'
       MongoDatabase database = mongoClient.getDatabase("test");

       // Access collection named 'restaurants'
       MongoCollection<Document> collection = database.getCollection("restaurants");

       // 2. Insert 
       List<Document> documents = asList(
               new Document("name", "Sun Bakery Trattoria")
                       .append("stars", 4)
                       .append("categories", asList("Pizza", "Pasta", "Italian", "Coffee", "Sandwiches")),
               new Document("name", "Blue Bagels Grill")
                       .append("stars", 3)
                       .append("categories", asList("Bagels", "Cookies", "Sandwiches")),
               new Document("name", "Hot Bakery Cafe")
                       .append("stars", 4)
                       .append("categories", asList("Bakery", "Cafe", "Coffee", "Dessert")),
               new Document("name", "XYZ Coffee Bar")
                       .append("stars", 5)
                       .append("categories", asList("Coffee", "Cafe", "Bakery", "Chocolates")),
               new Document("name", "456 Cookies Shop")
                       .append("stars", 4)
                       .append("categories", asList("Bakery", "Cookies", "Cake", "Coffee")));

       collection.insertMany(documents);


       // 3. Query 
       List<Document> results = collection.find().into(new ArrayList<>());


       // 4. Create Index 
       collection.createIndex(Indexes.ascending("name"));
       // 5. Perform Aggregation
       collection.aggregate(asList(match(eq("categories", "Bakery")),
               group("$stars", sum("count", 1))));


        mongoClient.close();

   }

}

支援語言

安裝方法

客戶端選擇

springboot整合mongodb

依賴

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

配置

spring:
  data:
    mongodb:
      #uri配置
      #  如果有密碼 mongodb://user:pass@localhost:27017/test
      #  如果叢集 mongodb://user:pass@ip1:port1,ip2:port2/database
      uri: mongodb://localhost:27017/test

目前spring-data-starter-mongo並沒有提供連線池配置。如需要自己配置,參考

王靜茜 Spring Boot中使用MongoDB的連線池配置

翟永超 Spring Boot中增強對MongoDB的配置(連線池等)

使用MongoTemplate

mongoTemplate可以靈活的操作mongodb,如基本的CRUD、統計、聚合等

簡單CURD

實體類

public class User {
    private String id;
    private String name;
    private int age = 18;
    private LocalDateTime createTime = LocalDateTime.now();
}

介面測試類

@RestController
public class UserResource {

    @Autowired
    private MongoTemplate mongoTemplate;
    //新增
    @PostMapping("/template/user")
    public User save(@RequestBody User user){
        return mongoTemplate.save(user);
    }
    //查詢所有
    @GetMapping("/template/user")
    public List<User> findAll(){
        return mongoTemplate.findAll(User.class);
    }
    //根據姓名查詢
    @GetMapping("/template/user/{name}")
    public User findOne(@PathVariable String name){
        return mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)), User.class);
    }
}

測試

新增一個使用者 POST http://localhost:8080/template/user

檢視mongodb

呼叫查詢介面 GET http://localhost:8080/template/user

[
    {
        "id": "5c061052f94458c11e167a5a",
        "name": "test",
        "age": 13,
        "createTime": "2018-12-04T13:27:46.633"
    }
]

根據姓名查詢 GET http://localhost:8080/template/user/test

{
    "id": "5c061052f94458c11e167a5a",
    "name": "test",
    "age": 13,
    "createTime": "2018-12-04T13:27:46.633"
}

mongotemplate聚合統計

新建一個實體

@Data
public class Stu {
    private String id;
    private String name;
    private int sex = 1;//1男 2女
    private int age;
    private String grade;//年級
    private String school;//學校
}

新增單元測試,來新增測試資料

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MongoApp.class)
public class StuTest {
    @Autowired private MongoTemplate mongoTemplate;


    Random random = new Random();
    @Test
    public void addStus(){
        List<Stu> list = new ArrayList<>(20);
        for(int i = 0; i<20;i++){
            Stu stu = new Stu();
            stu.setName("學生" + i);
            stu.setSex(i%2 == 0 ? 1 : 2);
            stu.setAge(random.nextInt(20) + 5);
            stu.setGrade((random.nextInt(4) + 1) + "年級");
            stu.setSchool("第" + (random.nextInt(4) + 1) + "學校");
            list.add(stu);
        }
        mongoTemplate.insertAll(list);
    }
}

執行單元測試後,檢視mongo的資料

統計的測試介面

/**------------ MongoTemplate 聚合統計 -------------*/

    /**根據自定義欄位分組統計*/
    @GetMapping("/template/group/{groupFiled}")
    public Iterator<BasicDBObject> groupBase(@PathVariable String groupFiled){
        Aggregation agg = Aggregation.newAggregation(Aggregation.group(groupFiled).count().as("總人數"));
        AggregationResults<BasicDBObject> res = mongoTemplate.aggregate(agg, "stu", BasicDBObject.class);
        Iterator<BasicDBObject> iterator = res.iterator();
        return iterator;
    }

    /**按條件,根據多個欄位分組*/
    @GetMapping("/template/group")
    public Iterator<BasicDBObject> groupWithQueryCondition(){
        Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("age").gte(10)),
                Aggregation.group("school", "grade").count().as("總人數"),
                Aggregation.project("總人數").and("分組欄位").previousOperation()//顯示分組欄位,不顯示_id
        );
        AggregationResults<BasicDBObject> res = mongoTemplate.aggregate(agg, "stu", BasicDBObject.class);
        Iterator<BasicDBObject> iterator = res.iterator();
        return iterator;
    }

測試

  • 根據年級統計 GET http://localhost:8080/template/group/grade

  • 根據學校統計 GET http://localhost:8080/template/group/school

  • 多條件多欄位統計 GET http://localhost:8080/template/group

MongoRepository使用

定義一個介面,繼承MongoRepository,然後可以使用基於JPA的mongo操作了

public interface UserRepository extends MongoRepository<User, String> {

    User findByName(String name);
}

使用

    /**------------ MongoRepository -------------*/
    @Autowired private UserRepository userRepository;
	
    @PostMapping("/repository/user")
    public User save1(@RequestBody User user){
        return userRepository.save(user);
    }

    @GetMapping("/repository/user")
    public List<User> findAll1(){
        return userRepository.findAll();
    }

    @GetMapping("/repository/user/{name}")
    public User findOne1(@PathVariable String name){
        return userRepository.findByName(name);//自定義方法
    }

專案原始碼

https://gitee.com/yimingkeji/springboot/tree/master/mongo