最近進(jìn)行MongoDB開發(fā)叮阅,雖然需求比較簡(jiǎn)單,但是涉及較多的細(xì)節(jié)使用泣特。加之不夠熟悉 就使用了各種方法達(dá)到目標(biāo)浩姥。
1.簡(jiǎn)介
MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù),一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品状您,是非關(guān)系數(shù)據(jù)庫(kù)當(dāng)中功能最豐富及刻,最像關(guān)系數(shù)據(jù)庫(kù)的。
MongoDB 將數(shù)據(jù)存儲(chǔ)為一個(gè)文檔竞阐,數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對(duì)組成缴饭。MongoDB 文檔類似于 JSON 對(duì)象。字段值可以包含其他文檔骆莹,數(shù)組及文檔數(shù)組颗搂。支持比較豐富和復(fù)雜的數(shù)據(jù)類型。
MongoDB已經(jīng)在多個(gè)站點(diǎn)部署幕垦,其主要場(chǎng)景如下:
1)網(wǎng)站實(shí)時(shí)數(shù)據(jù)處理丢氢。它非常適合實(shí)時(shí)的插入傅联、更新與查詢,并具備網(wǎng)站實(shí)時(shí)數(shù)據(jù)存儲(chǔ)所需的復(fù)制及高度伸縮性疚察。
2)緩存蒸走。由于性能很高,它適合作為信息基礎(chǔ)設(shè)施的緩存層貌嫡。在系統(tǒng)重啟之后比驻,由它搭建的持久化緩存層可以避免下層的數(shù)據(jù)源過(guò)載。
3)高伸縮性的場(chǎng)景岛抄。非常適合由數(shù)十或數(shù)百臺(tái)服務(wù)器組成的數(shù)據(jù)庫(kù)别惦,它的路線圖中已經(jīng)包含對(duì)MapReduce引擎的內(nèi)置支持。
不適用的場(chǎng)景如下:
1)要求高度事務(wù)性的系統(tǒng)夫椭。
2)傳統(tǒng)的商業(yè)智能應(yīng)用掸掸。
3)復(fù)雜的跨文檔(表)級(jí)聯(lián)查詢。
2.使用
連接和認(rèn)證——方式一( MongoClient )
使用mongoclient的方式蹭秋。MongoClient是線程安全的扰付,可以在多程程環(huán)境中共享同一個(gè)MongoClient。通常來(lái)說(shuō)仁讨,一個(gè)應(yīng)用程序中悯周,只需要生成一個(gè)全局的MongoClient實(shí)例,然后在程序的其他地方使用這個(gè)實(shí)例即可陪竿。
直接連接:
MongoClient mongoClient = new MongoClient("localhost", 27017); // 獲取鏈接
MongoDatabase database = mongoClient.getDatabase("mydb"); // 獲取數(shù)據(jù)庫(kù)
認(rèn)證與連接:
MongoClientOptions.Builder builder = MongoClientOptions.builder(); //可以通過(guò)builder做各種詳細(xì)配置 MongoClientOptions myOptions = builder.build();
ArrayList<ServerAddress> serverAddressList = new ArrayList();
ServerAddress record = new ServerAddress("localhost", 27017); //IP、端口
serverAddressList.add(record); //用戶名屠橄、默認(rèn)庫(kù)名族跛、密碼
MongoCredential credential = MongoCredential.createCredential("賬號(hào)", "默認(rèn)庫(kù)名", "密碼".toCharArray());
MongoClient mongoClient = new MongoClient(serverAddressList, credential, myOptions);
連接和認(rèn)證——方式二( MongoClientURI)
直接使用MongoClientURI完成MongoDB的認(rèn)證,它代表了一個(gè)URI對(duì)象锐墙。MongoClientURI的構(gòu)造函數(shù)接受一個(gè)String類型的字符串礁哄,這個(gè)字符串的格式如下:
String sURI = String.format(
“mongodb://%s:%s@%s:%d/%s”, ”用戶名“, ”密碼“, ”localhost“, 27017, ”數(shù)據(jù)庫(kù)");
MongoClientURI uri = new MongoClientURI(sURI);
MongoClient mongoClient = new MongoClient(uri);
DB db = mongoClient.getDB(“數(shù)據(jù)庫(kù)");
MongoClientOptions.Builder mongoBuilder = new MongoClientOptions.Builder(); mongoBuilder.maxWaitTime(1000603);
mongoBuilder.connectTimeout(6010003); //與數(shù)據(jù)庫(kù)建立連接的timeout設(shè)置為1分鐘 mongoBuilder.minConnectionsPerHost(1);
MongoClientURI mongoClientURI = new MongoClientURI(“mongodb://root:root@localhost:27017/數(shù)據(jù)庫(kù)",mongoBuilder);
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClientURI); MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
連接和認(rèn)證——方式三( MongoTemplate)
public MongoClient mongoClient() {
MongoCredential credential = MongoCredential.createCredential(“用戶”, "數(shù)據(jù)庫(kù)", “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ù)庫(kù)");
}
CRUD——方式一
基于注解的方式:
1.實(shí)體上使用 @Document(collection = ”UserDO")
2.繼承MongoRepository,簡(jiǎn)單的增刪改查無(wú)需實(shí)現(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ù)訪問(wèn)功能桐绒,其幾個(gè)子接口則擴(kuò)展了一些功能。它們的繼承關(guān)系如下:
Repository:僅僅是一個(gè)標(biāo)識(shí)之拨,表明任何繼承它的均為倉(cāng)庫(kù)接口類
CrudRepository:繼承Repository茉继,實(shí)現(xiàn)了一組CRUD相關(guān)的方法
PagingAndSortingRepository:繼承CrudRepository,實(shí)現(xiàn)了一組分頁(yè)排序相關(guān)的方法
JpaRepository:繼承PagingAndSortingRepository蚀乔,實(shí)現(xiàn)一組JPA規(guī)范相關(guān)的方法
自定義的XxxxRepository需要繼承 JpaRepository烁竭,這樣的XxxxRepository接口就具備了通用的數(shù)據(jù)訪問(wèn)控制層的能力。
JpaSpecificationExecutor:不屬于Repository體系吉挣,實(shí)現(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)計(jì)
collection.createIndex(); collection. dropIndex(); //增加刪除索引
collection.createIndexs(); collection. dropIndexs(); //批量增加刪除索引
collection.replaceOne();//替換文檔
collection.distinct();//返回具有指定字段不同值的文檔(去除指定字段的重復(fù)數(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(相當(dāng)于 WHERE 或者 HAVING )
BasicDBObject group = new BasicDBObject("subject") //group(相當(dāng)于 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ù)婉弹,分頁(yè)時(shí)使用)
BasicDBObject skip = new BasicDBObject("$skip", xx); //skip(跳過(guò)前面多少條數(shù)據(jù),分頁(yè)時(shí)使用)
List<DBObject> queryList = new ArrayList<>(); //queryList集合里的順序不能亂终吼,否則會(huì)報(bào)錯(cuò)镀赌。
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——分頁(yè)查詢
方式一:使用limit和skip進(jìn)行分頁(yè)find().skip((pageNum-1)*pageSize).sort().limit(pageSize)
方式二:通過(guò)原生的方法實(shí)現(xiàn)條件查詢、分頁(yè)和排序
方式三:通過(guò)實(shí)現(xiàn)Pageable接口等方式做自定義實(shí)現(xiàn)
find(索引).projection(查詢字段).sort().limit()