最近進行MongoDB開發(fā),雖然需求比較簡單,但是涉及較多的細節(jié)使用。加之不夠熟悉 就使用了各種方法達到目標。
1.簡介
MongoDB是一個基于分布式文件存儲的數(shù)據(jù)庫,一個介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫當中功能最豐富,最像關(guān)系數(shù)據(jù)庫的。
MongoDB 將數(shù)據(jù)存儲為一個文檔,數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對組成。MongoDB 文檔類似于 JSON 對象。字段值可以包含其他文檔,數(shù)組及文檔數(shù)組。支持比較豐富和復雜的數(shù)據(jù)類型。
MongoDB已經(jīng)在多個站點部署,其主要場景如下:
1)網(wǎng)站實時數(shù)據(jù)處理。它非常適合實時的插入、更新與查詢,并具備網(wǎng)站實時數(shù)據(jù)存儲所需的復制及高度伸縮性。
2)緩存。由于性能很高,它適合作為信息基礎(chǔ)設(shè)施的緩存層。在系統(tǒng)重啟之后,由它搭建的持久化緩存層可以避免下層的數(shù)據(jù)源過載。
3)高伸縮性的場景。非常適合由數(shù)十或數(shù)百臺服務(wù)器組成的數(shù)據(jù)庫,它的路線圖中已經(jīng)包含對MapReduce引擎的內(nèi)置支持。
不適用的場景如下:
1)要求高度事務(wù)性的系統(tǒng)。
2)傳統(tǒng)的商業(yè)智能應(yīng)用。
3)復雜的跨文檔(表)級聯(lián)查詢。
2.使用
連接和認證——方式一( MongoClient )
使用mongoclient的方式。MongoClient是線程安全的,可以在多程程環(huán)境中共享同一個MongoClient。通常來說,一個應(yīng)用程序中,只需要生成一個全局的MongoClient實例,然后在程序的其他地方使用這個實例即可。
直接連接:
MongoClient mongoClient = new MongoClient("localhost", 27017); // 獲取鏈接
MongoDatabase database = mongoClient.getDatabase("mydb"); // 獲取數(shù)據(jù)庫
認證與連接:
MongoClientOptions.Builder builder = MongoClientOptions.builder(); //可以通過builder做各種詳細配置 MongoClientOptions myOptions = builder.build();
ArrayList<ServerAddress> serverAddressList = new ArrayList();
ServerAddress record = new ServerAddress("localhost", 27017); //IP、端口
serverAddressList.add(record); //用戶名、默認庫名、密碼
MongoCredential credential = MongoCredential.createCredential("賬號", "默認庫名", "密碼".toCharArray());
MongoClient mongoClient = new MongoClient(serverAddressList, credential, myOptions);
連接和認證——方式二( MongoClientURI)
直接使用MongoClientURI完成MongoDB的認證,它代表了一個URI對象。MongoClientURI的構(gòu)造函數(shù)接受一個String類型的字符串,這個字符串的格式如下:
String sURI = String.format(
“mongodb://%s:%s@%s:%d/%s”, ”用戶名“, ”密碼“, ”localhost“, 27017, ”數(shù)據(jù)庫");
MongoClientURI uri = new MongoClientURI(sURI);
MongoClient mongoClient = new MongoClient(uri);
DB db = mongoClient.getDB(“數(shù)據(jù)庫");
MongoClientOptions.Builder mongoBuilder = new MongoClientOptions.Builder(); mongoBuilder.maxWaitTime(1000603);
mongoBuilder.connectTimeout(6010003); //與數(shù)據(jù)庫建立連接的timeout設(shè)置為1分鐘 mongoBuilder.minConnectionsPerHost(1);
MongoClientURI mongoClientURI = new MongoClientURI(“mongodb://root:root@localhost:27017/數(shù)據(jù)庫",mongoBuilder);
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClientURI); MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
連接和認證——方式三( MongoTemplate)
public MongoClient mongoClient() {
MongoCredential credential = MongoCredential.createCredential(“用戶”, "數(shù)據(jù)庫", “password”);
return MongoClients.create(
MongoClientSettings.builder()
.applyToClusterSettings(builder ->
builder.applyConnectionString(new ConnectionString(serverList)))
.credential(credential)
.applicationName("應(yīng)用")
.readConcern(ReadConcern.MAJORITY)
.readPreference(ReadPreference.primaryPreferred())
.writeConcern(WriteConcern.MAJORITY)
.applyToConnectionPoolSettings(builder -> {
builder
.maxWaitTime(1, TimeUnit.SECONDS)
.maxSize(10);
})
.applyToSocketSettings(builder -> builder
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS))
.build());
}
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(), "數(shù)據(jù)庫");
}
CRUD——方式一
基于注解的方式:
1.實體上使用 @Document(collection = ”UserDO")
2.繼承MongoRepository,簡單的增刪改查無需實現(xiàn),可直接使用
@Repository
public interface UserExtRepository extends MongoRepository<UserDO, String> {
List<UserDO> findById(String id);
}
xxRepository.insert(UserDO);
xxRepository. findBy(”11”);
Repositry接口
基礎(chǔ)的 Repository提供了最基本的數(shù)據(jù)訪問功能,其幾個子接口則擴展了一些功能。它們的繼承關(guān)系如下:
Repository:僅僅是一個標識,表明任何繼承它的均為倉庫接口類
CrudRepository:繼承Repository,實現(xiàn)了一組CRUD相關(guān)的方法
PagingAndSortingRepository:繼承CrudRepository,實現(xiàn)了一組分頁排序相關(guān)的方法
JpaRepository:繼承PagingAndSortingRepository,實現(xiàn)一組JPA規(guī)范相關(guān)的方法
自定義的XxxxRepository需要繼承 JpaRepository,這樣的XxxxRepository接口就具備了通用的數(shù)據(jù)訪問控制層的能力。
JpaSpecificationExecutor:不屬于Repository體系,實現(xiàn)一組JPACriteria查詢相關(guān)的方法
CRUD——方式二
增:
MongoCollection<Document> collection = mongo.getDb(“database”).getCollection(“CollectionName”);
Document document = Document.parse(JSONObject.toJSONString(userDO));
collection.insertOne(document);
collection.insertMany(document);
刪:
MongoCollection<Document> collection = mongo.getDb(database).getCollection(“collection”);
BasicDBObject queryObject = new BasicDBObject(”id“,”1111“);
collection.deleteOne(queryObject);
collection.deleteMany(queryObject);
改:
MongoCollection<Document> collection = mongo.getDb(“database”).getCollection(“collection”);
BasicDBObject queryObject = new BasicDBObject(“id”,“1111”);
BasicDBObject updateNewOneSql = new BasicDBObject(“$set”, new BasicDBObject(“name”, “tom”));
collection.updateOne(queryObject, updateNewOneSql);
collection. updateMany();
collection. findOneAndUpdate();
查:
MongoCollection<Document> collection = mongo.getDb(database).getCollection(“collection”);
BasicDBObject queryObject = new BasicDBObject(”id“,”1111“);
FindIterable<Document> documents = collection.find(queryObject);
other:
collection.aggregate();//聚合索引
collection.countDocuments();//統(tǒng)計
collection.createIndex(); collection. dropIndex(); //增加刪除索引
collection.createIndexs(); collection. dropIndexs(); //批量增加刪除索引
collection.replaceOne();//替換文檔
collection.distinct();//返回具有指定字段不同值的文檔(去除指定字段的重復數(shù)據(jù))
collection.bulkWrite();//批量寫入
collection.dataSize();//返回集合大小
collection.drop(); //刪除集合
聚合查詢:
BasicDBObject query= new BasicDBObject();
BasicDBObject[] array = { new BasicDBObject("time", new BasicDBObject("lte","2018-12-25"))};
query.append("$and", array);
BasicDBObject match = new BasicDBObject("$match", query); // match(相當于 WHERE 或者 HAVING )
BasicDBObject group = new BasicDBObject("subject") //group(相當于 GROUP BY)
.append("count", new BasicDBObject("$sum", 1)));
BasicDBObject sort = new BasicDBObject("$sort", new BasicDBObject("count", -1));//1:正序,-1倒序
BasicDBObject limit = new BasicDBObject("$limit", pageSize); //limt(只要前多少條數(shù)據(jù),分頁時使用)
BasicDBObject skip = new BasicDBObject("$skip", xx); //skip(跳過前面多少條數(shù)據(jù),分頁時使用)
List<DBObject> queryList = new ArrayList<>(); //queryList集合里的順序不能亂,否則會報錯。
queryList .add(match);
queryList .add(group);
queryList .add(sort);
queryList .add(skip);
queryList .add(limit);
AggregateIterable<Document> iterable = mongoClient.mongoClient.getDatabase(dbName).getCollection(gatherName).aggregate(queryList );
CRUD——分頁查詢
方式一:使用limit和skip進行分頁find().skip((pageNum-1)*pageSize).sort().limit(pageSize)
方式二:通過原生的方法實現(xiàn)條件查詢、分頁和排序
方式三:通過實現(xiàn)Pageable接口等方式做自定義實現(xiàn)
find(索引).projection(查詢字段).sort().limit()
