關於MongoDB的簡單理解(二)--Java篇

學海無涯519發表於2021-01-30

一、宣告

  • 本文依賴於 MongoDB JVM DRIVERS 4.1 版本編寫。
  • 本文案例依賴於 Maven 專案管理工具。

二、本文主要講解哪些內容?

  • 如何連線到MongoDB
  • 通過TLS/SSL連線MongoDB
  • 認證方式
  • 壓縮
  • 讀取/寫入操作
  • 建立索引
  • 文字搜尋
  • 網格FS

三、環境準備

官方描述:

  MongoDB驅動程式mongodb-driver-sync是同步Java驅動程式,僅包含MongoCollection符合新的交叉驅動程式CRUD規範的通用介面。

使用方式:

  新增如下依賴。

1 <dependencies>
2     <dependency>
3         <groupId>org.mongodb</groupId>
4         <artifactId>mongodb-driver-sync</artifactId>
5         <version>4.1.1</version>
6     </dependency>
7 </dependencies>

四、Java操作MongoDB

強心針:

  java操作MongoDb非常簡單,主要有以下幾個步驟:

  例項化MongoClient物件 --> 訪問資料庫  --> 訪問集合 --> 運算元據

1.如何連線到MongoDB?

官方描述:

  自3.7版本開始,建議使用 MongoClients.create() 建立連線,也可以用舊版的 MongoClient() 建立連線。

注意事項:

  預設情況下,3.5版本棄用的套接字保持活動設定以及套接字保持活動檢查現在處於啟用狀態。強烈建議該系統保持活動設定應該更短的超時配置。

連線 MongoDB單例 程式碼實現:

 1 public static void main(String[] args) {
 2 
 3     // 連線方式1
 4     // 可以例項化一個不帶任何引數的MongoClient物件,以連線到埠在本地主機上執行的MongoDB例項27017
 5     MongoClient mongoClient = MongoClients.create();
 6 
 7     // 連線方式2
 8     // 可以顯式指定主機名,以連線到在埠上的指定主機上執行的MongoDB例項27017
 9     MongoClient mongoClient = MongoClients.create(
10             MongoClientSettings.builder()
11                     .applyToClusterSettings(builder ->
12                             builder.hosts(Arrays.asList(new ServerAddress("127.0.0.1")))).build()
13     );
14 
15     // 連線方式3
16     // 可以顯式指定主機名和埠:
17     MongoClient mongoClient = MongoClients.create(
18             MongoClientSettings.builder()
19                     .applyToClusterSettings(builder ->
20                             builder.hosts(Arrays.asList(new ServerAddress("127.0.0.1", 27017))))
21                     .build()
22     );
23 
24     // 連線方式4
25     // 顯式指定主機名和埠
26     MongoClient mongoClient = MongoClients.create("mongodb://127.0.0.1:27017");
27     
28 }

連線到副本集:

 1 public static void main(String[] args) {
 2 
 3     // 您可以使用來指定成員ConnectionString(指定副本集的至少兩個成員)
 4     MongoClient mongoClient = MongoClients.create("mongodb://host1:27017,host2:27017,host3:27017");
 5 
 6     // 使用副本集的至少一個成員和replicaSet(複製集)指定副本集名稱的選項
 7     MongoClient mongoClient = MongoClients.create("mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=myReplicaSet");
 8 
 9     // 您可以指定所有副本整合員的列表ServerAddress
10     MongoClient mongoClient = MongoClients.create(
11             MongoClientSettings.builder()
12                     .applyToClusterSettings(builder ->
13                             builder.hosts(Arrays.asList(
14                                     new ServerAddress("host1", 27017),
15                                     new ServerAddress("host2", 27017),
16                                     new ServerAddress("host3", 27017))))
17                     .build());
18 }

2.通過TLS/SSL連線MongoDB

官方描述:

  Java驅動程式使用JDK提供的TLS / SSL底層支援來支援與MongoDB伺服器的TLS / SSL連線。

程式碼示例:

 1 public static void main(String[] args) {
 2 
 3     // 直接指定TLS/SSL ConnectionString,使 ssl=true 為連線字串的一部分
 4     MongoClient mongoClient = MongoClients.create("mongodb://localhost/?ssl=true");
 5 
 6     // 指定TLS/SSL MongoClientSettings,將enabled屬性設定為 true
 7     MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
 8             .applyToSslSettings(builder ->
 9                     builder.enabled(true))
10             .build();
11     MongoClient mongoClient1 = MongoClients.create(mongoClientSettings);
12 
13     // SSLContext: 此類的例項表示安全套接字協議的實現, 它是SSLSocketFactory、SSLServerSocketFactory和SSLEngine的工廠。
14     // 通過 SSLContext 指定 MongoClientSettings
15 
16     X509TrustManager x509m = new X509TrustManager() {
17 
18         @Override
19         public X509Certificate[] getAcceptedIssuers() {
20             return null;
21         }
22 
23         @Override
24         public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
25         }
26 
27         @Override
28         public void checkClientTrusted(X509Certificate[] chain,
29                                        String authType) throws CertificateException {
30         }
31     };
32 
33     // 獲取一個SSLContext例項
34     SSLContext sslContext = null;
35     try {
36         sslContext = SSLContext.getInstance("SSL");
37         // 初始化SSLContext例項
38         sslContext.init(null, new TrustManager[] { x509m },
39                 new java.security.SecureRandom());
40     } catch (Exception e) {
41         e.printStackTrace();
42     }
43 
44     SSLContext finalSslContext = sslContext;
45     MongoClientSettings settings = MongoClientSettings.builder()
46             .applyToSslSettings(builder -> {
47                 builder.enabled(true);
48                 builder.context(finalSslContext);
49             })
50             .build();
51     MongoClient client = MongoClients.create(settings);
52 
53     // 禁用主機名驗證
54     // 預設情況下,驅動程式確保伺服器SSL證照中包含的主機名與構造時提供的主機名匹配
55     MongoClientSettings mongoClientSettings1 = MongoClientSettings.builder()
56             .applyToSslSettings(builder -> {
57                 builder.enabled(true);
58                 builder.invalidHostNameAllowed(true);
59             })
60             .build();
61     MongoClient client1 = MongoClients.create(mongoClientSettings1);
62 
63 }

3.認證方式

官方描述:

  • 在MongoDB 3.0中,MongoDB將預設的身份驗證機制從MongoDB-CR更改為SCRAM-SHA-1。
  • 在MongoDB 4.0中,取消了對不推薦使用的MongoDB-CR機制的支援,並新增了對SCRAM-SHA-256的支援。

程式碼描述:

第一種方式:

 1 public static void main(String[] args) {
 2 
 3     // 使用者名稱
 4     String user = "mydb";
 5     // 定義使用者的源
 6     String source = "mydb";
 7     // 密碼字元陣列
 8     char[] password = "mydb".toCharArray();
 9     
10     MongoCredential credential = MongoCredential.createScramSha1Credential(user, source, password);
11 
12     MongoClient mongoClient = MongoClients.create(
13             MongoClientSettings.builder()
14                     .applyToClusterSettings(builder ->
15                             builder.hosts(Arrays.asList(new ServerAddress("127.0.0.1", 27017))))
16                     .credential(credential)
17                     .build());
18 
19 }

第二種方式:

1 // 連線Mongo
2 MongoClient mongoClient = MongoClients.create("mongodb://mydb:mydb@127.0.0.1:27017");

憑證建立方式

SCRAM-SHA-1 憑證

1 // 使用者名稱
2 String user = "mydb";
3 // 定義使用者的源
4 String source = "mydb";
5 // 密碼字元陣列
6 char[] password = "mydb".toCharArray();
7 
8 // 建立SCRAM-SHA-1 憑證
9 MongoCredential credential = MongoCredential.createScramSha1Credential(user, source, password);

SCRAM-SHA-256 憑證

1 // 使用者名稱
2 String user = "mydb";
3 // 定義使用者的源
4 String source = "mydb";
5 // 密碼字元陣列
6 char[] password = "mydb".toCharArray();
7 
8 // SCRAM-SHA-256 憑證
9 MongoCredential credential = MongoCredential.createScramSha256Credential(user, source, password);

MONGODB-CR 憑證

1 // 使用者名稱
2 String user = "mydb";
3 // 定義使用者的源
4 String source = "mydb";
5 // 密碼字元陣列
6 char[] password = "mydb".toCharArray();
7 
8 // MONGODB-CR 憑證
9 MongoCredential credential = MongoCredential.createMongoCRCredential(user, database, password);

X.509 憑證

1 // 使用者名稱
2 String user = "mydb";
3 
4 // X.509 憑證
5 MongoCredential credential = MongoCredential.createMongoX509Credential(user);

Kerberos (GSSAPI) 憑證

1 // 使用者名稱
2 String user = "mydb";
3 
4 // Kerberos (GSSAPI) 憑證
5 MongoCredential credential = MongoCredential.createGSSAPICredential(user);

LDAP (PLAIN) 憑證

1 // 使用者名稱
2 String user = "mydb";
3 // 密碼字元陣列
4 char[] password = "mydb".toCharArray();
5 
6 // LDAP (PLAIN)憑證
7 MongoCredential credential = MongoCredential.createPlainCredential(user, "$external", password);

4. 壓縮

官方描述:

  Java驅動程式支援與MongoDB伺服器之間的訊息壓縮。該驅動程式實現了MongoDB伺服器支援的三種演算法:

  • Snappy:從3.4版本開始連線到MongoDB伺服器時,可以使用Snappy壓縮。
  • Zlib:從3.6版本開始連線到MongoDB伺服器時,可以使用Zlib壓縮。
  • Zstandard:從4.2版本開始連線到MongoDB伺服器時,可以使用Zstandard壓縮。

程式碼示例:

通過ConnectionString方式執行壓縮機:
 1 public static void main(String[] args) {
 2 
 3     // 通過ConnectionString方式執行壓縮機
 4     // 用Snappy壓縮
 5     ConnectionString connectionString = new ConnectionString("mongodb://localhost/?compressors=snappy");
 6     MongoClients.create(connectionString);
 7 
 8     // 用zlib壓縮
 9     ConnectionString connectionString = new ConnectionString("mongodb://localhost/?compressors=zlib");
10     MongoClient mongoClient = MongoClients.create(connectionString);
11 
12     // 用Zstandard壓縮
13     ConnectionString connectionString = new ConnectionString("mongodb://localhost/?compressors=zstd");
14     MongoClient mongoClient = MongoClients.create(connectionString);
15 
16     // 配置多個壓縮機
17     // 注意: 在所有情況下,驅動程式都將使用伺服器為其提供支援的列表中的第一個壓縮器
18     ConnectionString connectionString = new ConnectionString("mongodb://localhost/?compressors=snappy,zlib,zstd");
19     MongoClient mongoClient = MongoClients.create(connectionString);
20 
21 }
通過MongoClientSettings指定壓縮機
 1 public static void main(String[] args) {
 2 
 3     // 通過MongoClientSettings指定壓縮機
 4 
 5     // 用Snappy壓縮
 6     MongoClientSettings settings = MongoClientSettings.builder()
 7             .compressorList(Arrays.asList(MongoCompressor.createSnappyCompressor()))
 8             .build();
 9     MongoClient client = MongoClients.create(settings);
10 
11     // 用zlib壓縮
12     MongoClientSettings settings = MongoClientSettings.builder()
13             .compressorList(Arrays.asList(MongoCompressor.createZlibCompressor()))
14             .build();
15     MongoClient client = MongoClients.create(settings);
16 
17     // 用Zstandard壓縮
18     MongoClientSettings settings = MongoClientSettings.builder()
19             .compressorList(Arrays.asList(MongoCompressor.createZstdCompressor()))
20             .build();
21     MongoClient client = MongoClients.create(settings);
22 
23     // 配置多個壓縮機
24     // 注意: 在所有情況下,驅動程式都將使用伺服器為其提供支援的列表中的第一個壓縮器
25     MongoClientSettings settings = MongoClientSettings.builder()
26             .compressorList(Arrays.asList(MongoCompressor.createSnappyCompressor(),
27                     MongoCompressor.createZlibCompressor(),
28                     MongoCompressor.createZstdCompressor()))
29             .build();
30     MongoClient client = MongoClients.create(settings);
31 
32 }

注意:

  • 由於JDK不對SnappyZstandard內建支援,因此驅動程式依賴現有的開源Snappy和Zstandard實現
  • 驅動程式將根據ismaster命令響應中伺服器通告的功能,如果有壓縮演算法的話,會自動協商使用哪種壓縮演算法。

Snappy擴充套件:

  snappy-java是snappy的Java埠,Snappy是Google開發的快速C ++壓縮器/解壓縮器。

  特點為 速度快記憶體佔用少跨平臺使用簡單免費

  Snappy引入方式:

1 <dependency>
2    <groupId>org.xerial.snappy</groupId>
3    <artifactId>snappy-java</artifactId>
4    <version>(version)</version>
5    <type>jar</type>
6    <scope>compile</scope>
7 </dependency>

  Snappy程式碼示例:

import org.xerial.snappy.Snappy;

String input = "Hello snappy-java! Snappy-java is a JNI-based wrapper of "
     + "Snappy, a fast compresser/decompresser.";
byte[] compressed = Snappy.compress(input.getBytes("UTF-8"));
byte[] uncompressed = Snappy.uncompress(compressed);

String result = new String(uncompressed, "UTF-8");
System.out.println(result);

//------------------------------
// 讀取/寫入大資料集(從1.1.3-M2開始)
import org.xerial.snappy.BitShuffle;

int[] data = new int[] {1, 3, 34, 43, 34};
byte[] shuffledByteArray = BitShuffle.shuffle(data);
byte[] compressed = Snappy.compress(shuffledByteArray);
byte[] uncompressed = Snappy.uncompress(compressed);
int[] result = BitShuffle.unshuffleIntArray(uncompress);

System.out.println(result);

Zstandard擴充套件:

  Zstd本機庫的JNI繫結為Android,Java和所有JVM語言提供了快速,高壓縮的無損演算法。

  特點是 靜態壓縮/解壓縮方法、InputStream和OutputStream的實現、效能開銷小

  引入方式:

1 <dependency>
2     <groupId>com.github.luben</groupId>
3     <artifactId>zstd-jni</artifactId>
4     <version>VERSION</version>
5     <classifier>linux_amd64</classifier>
6 </dependency>

ismaster擴充套件:

  • isMaster返回描述mongod例項角色的文件如果saslSupportedMechs指定了可選欄位 ,該命令還將返回 用於建立指定使用者憑證的。
  • 如果例項是副本集的成員,則isMaster返回副本集配置和狀態的子集,包括例項是否為副本集副本。
  • 當傳送到mongod不是副本整合員的例項時,isMaster返回此資訊的子集。
  • MongoDB驅動程式客戶端用於 isMaster確定副本整合員的狀態並發現副本集的其他成員

  ismaster語法:

1 db.runCommand( { isMaster: 1 } )
2 
3 // 從MongoDB 4.0開始,該isMaster命令接受可選欄位,以在其結果中返回附加欄位並新增與該命令關聯的日誌註釋
4 db.runCommand( { isMaster: 1, saslSupportedMechs: "<db.username>", comment: <any> } )

5.讀取/寫入操作

  讀取和寫入比較簡單,這邊直接上程式碼

使用Document類建立文件:

 1 public static void main(String[] args) {
 2 
 3     // 連線方式
 4     MongoClient mongoClient = MongoClients.create("mongodb://mydb:mydb@127.0.0.1:27017");
 5 
 6     // 放問資料庫
 7     // 如果資料庫不存在,則在第一次為該資料庫 儲存資料 時,MongoDB會建立該資料庫
 8     // 注意:MongoDatabase 例項是不可變的
 9     MongoDatabase database = mongoClient.getDatabase("mydb");
10 
11     // 訪問集合
12     // 不存在集合,則在第一次為該集合 儲存資料 時,MongoDB會建立該集合
13     MongoCollection<Document> collection = database.getCollection("test");
14 
15     // 插入一個檔案
16     // 建立文字物件
17     Document doc = new Document("name", "MongoDB")
18             .append("type", "database")
19             .append("count", 1)
20             .append("versions", Arrays.asList("v3.2", "v3.0", "v2.6"))
21             .append("info", new Document("x", 203).append("y", 102));
22 
23     //插入檔案
24     collection.insertOne(doc);
25 
26     // 插入多個檔案
27     List<Document> documentList = new ArrayList<>();
28     for (int i = 0; i < 100; i++){
29         documentList.add(new Document("i", i));
30     }
31     collection.insertMany(documentList);
32 
33     // 計算集合中的文件
34     System.out.println("集合中的文件的數量為:" + collection.countDocuments());
35 
36     // 查詢集合中的第一個文件
37     // 如果集合為空,則操作返回null
38     Document first = collection.find().first();
39     System.out.println("集合中的第一個文件" + first.toJson());
40 
41     // 查詢集合中的所有文件
42     MongoCursor<Document> cursor = collection.find().iterator();
43     try {
44         while (cursor.hasNext()){
45             System.out.println(cursor.next().toJson());
46         }
47     }finally {
48         cursor.close();
49     }
50     // 查詢集合中的所有文件(不推薦做法--如果迴圈提前終止,則應用程式可能會洩漏遊標)
51     for (Document cur : collection.find()) {
52         System.out.println(cur.toJson());
53     }
54 
55     // 獲取與過濾器匹配的單個文件
56     Document singleDoc = collection.find(eq("i", 71)).first();
57     System.out.println("過濾器匹配的單個文件" + singleDoc.toJson());
58 
59     // 獲取與過濾器匹配的所有文件
60     Consumer<Document> printBlock = new Consumer<Document>() {
61         @Override
62         public void accept(Document document) {
63             System.out.println(document.toJson());
64         }
65     };
66     // "i" > 50
67     collection.find(gt("i",50)).forEach(printBlock);
68     // 50 < i <= 100
69     collection.find(and(gt("i", 50), lte("i", 100))).forEach(printBlock);
70 
71     // 更新單個文件
72     UpdateResult updateResult = collection.updateOne(eq("i", 110), set("i", 10));
73     System.out.println("更新檔案的數量為: " + updateResult.getModifiedCount());
74 
75     // 更新多個檔案
76     // 對所有小於100的文件,進行 +100 操作
77     UpdateResult updateResult1 = collection.updateMany(lt("i", 100), inc("i", 100));
78     System.out.println(updateResult1.getModifiedCount());
79 
80     // 刪除單個文件
81     DeleteResult deleteOne = collection.deleteOne(eq("i", 110));
82     System.out.println("刪除單個文件的數量" + deleteOne.getDeletedCount());
83 
84     // 刪除所有與過濾器匹配的文件
85     // 刪除i大於或等於100的所有文件
86     DeleteResult deleteMany = collection.deleteMany(gte("i", 100));
87     System.out.println("刪除多個文件的數量" + deleteMany.getDeletedCount());
88 
89 }

使用POJO建立文件(本例中使用lombok來簡化程式碼):

  1)建立Address實體

 1 @Data
 2 @EqualsAndHashCode(callSuper = false)
 3 @Accessors(chain = true)
 4 @NoArgsConstructor                 //無參構造
 5 @AllArgsConstructor                //有參構造
 6 public final class Address {
 7 
 8     private String street;
 9 
10     private String city;
11 
12     private String zip;
13 
14 }

  2)建立Person實體

 1 @Data
 2 @EqualsAndHashCode(callSuper = false)
 3 @Accessors(chain = true)
 4 @NoArgsConstructor                 //無參構造
 5 @AllArgsConstructor                //有參構造
 6 public class Person {
 7 
 8     private ObjectId id;
 9 
10     private String name;
11 
12     private int age;
13 
14     private Address address;
15 
16     public Person(String name, int age, Address address) {
17         this.name = name;
18         this.age = age;
19         this.address = address;
20     }
21 }

  3)建立測試方法

 1 public static void main(String[] args) {
 2  
 3      // 連線Mongo
 4      MongoClient mongoClient = MongoClients.create("mongodb://mydb:mydb@127.0.0.1:27017");
 5  
 6      // 結合預設的編解碼器登錄檔,並將其PojoCodecProvider配置為自動建立POJO Codec
 7      CodecRegistry pojoCodecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
 8              fromProviders(PojoCodecProvider.builder().automatic(true).build()));
 9  
10      // 放問資料庫
11      MongoDatabase database = mongoClient.getDatabase("mydb").withCodecRegistry(pojoCodecRegistry);
12  
13      // 配置了Pojo型別的例項
14      MongoCollection<Person> collection = database.getCollection("people", Person.class);
15  
16      // 插入一個人
17      Person person = new Person("Ada Byron", 20, new Address("St James Square", "London", "W1"));
18      collection.insertOne(person);
19  
20      // 插入很多人
21      List<Person> personList = Arrays.asList(
22          new Person("Charles Babbage", 45, new Address("5 Devonshire Street", "London", "W11")),
23          new Person("Alan Turing", 28, new Address("Bletchley Hall", "Bletchley Park", "MK12")),
24          new Person("Timothy Berners-Lee", 61, new Address("Colehill", "Wimborne", null))
25      );
26      collection.insertMany(personList);
27  
28      // 查詢集合
29      Consumer<Person> printBlock = new Consumer<Person>() {
30          @Override
31          public void accept(Person person) {
32              System.out.println(person);
33          }
34      };
35      collection.find().forEach(printBlock);
36  
37      // 符合條件的一個人
38      Person onePerson = collection.find(eq("address.city", "Wimborne")).first();
39      System.out.println("符合條件的人:" + onePerson);
40  
41      // 符合條件的很多人
42      collection.find(gt("age", 30)).forEach(printBlock);
43  
44      // 更新一個人
45      UpdateResult updateOne = collection.updateOne(eq("name", "Ada Byron"), combine(set("address.city", "bei jing"), set("age", "109")));
46      System.out.println("更新數量為:" + updateOne.getModifiedCount());
47  
48      // 更新很多人
49      UpdateResult updateMany = collection.updateMany(not(eq("address.zip", null)), set("address.zip", "MK15"));
50      System.out.println("更新數量為:" + updateMany.getModifiedCount());
51  
52      // 替換一個人
53      Person replacePerson = new Person("Xiao Ming", 29, new Address("bei jing", "bei jing", "W1"));
54      collection.replaceOne(eq("name", "Alan Turing"),replacePerson);
55  
56      DeleteResult deleteOne = collection.deleteOne(eq("address.city", "Wimborne"));
57      System.out.println("刪除數量:" + deleteOne.getDeletedCount());
58  
59      DeleteResult deleteMany = collection.deleteMany(eq("address.city", "bei jing"));
60      System.out.println("刪除數量:" + deleteMany.getDeletedCount());
61  
62      // 獲取集合名稱
63      database.listCollectionNames().forEach(System.out::println);
64  
65      // 慎用-- 刪除集合
66      collection.drop();
67      
68      // 投影文件(指定返回結果)
69      collection.find().projection(fields(include("name", "age"),excludeId())).sort(Sorts.descending("age")).forEach(printBlock);
70 }

6.建立索引

官方描述:

  索引支援在MongoDB中高效執行查詢。可以在一個或多個欄位上建立索引。

注意事項:

  MongoDB只在同一規範的索引不存在時建立索引。

程式碼示例:

 1 public static void main(String[] args) {
 2 
 3     // 建立單個上升索引
 4     collection.createIndex(Indexes.ascending("name"));
 5     // 建立複合上升索引
 6     collection.createIndex(Indexes.ascending("age","name"));
 7 
 8     // 建立單個降序索引
 9     collection.createIndex(Indexes.descending("name"));
10     // 建立複合降序索引
11     collection.createIndex(Indexes.descending("age","name"));
12 
13     // 複合索引
14     collection.createIndex(Indexes.compoundIndex(Indexes.ascending("start"), Indexes.descending("name")));
15 
16     // 文字索引
17     collection.createIndex(Indexes.text("name"));
18 
19     // 雜湊指數
20     // 在_id欄位上建立雜湊索引
21     collection.createIndex(Indexes.hashed("_id"));
22     collection.listIndexes().forEach(System.out::println);
23 24 }

7.文字搜尋

官方描述:

  • 利用Atlas Search,您可以輕鬆地在MongoDB資料之上構建基於相關性的快速搜尋功能
  • MongoDB使用文字索引和 $text查詢運算子更簡單的進行查詢操作
  • Java驅動程式提供了Filters.text()

程式碼示例:

  文字搜尋

1 // 例如,下面的程式碼在name欄位中執行文字搜尋,查詢單詞“bakery”或“coffee”。
2 long matchCount = collection.countDocuments(Filters.text("bakery coffee"));
3 System.out.println("Text search matches: " + matchCount);

  文字分數

1 // 文字分數
2 // 對於每個匹配的文件,文字搜尋都會分配一個分數,該分數表示文件與指定的文字搜尋查詢過濾器的相關性。要返回分數並按分數排序,請$meta在投影文件和排序表示式中使用運算子
3 collection.createIndex(Indexes.text("i"));
4 MongoCursor<Document> iterator = collection.find(text("9")).projection(Projections.metaTextScore("score"))
5         .sort(Sorts.metaTextScore("score")).iterator();
6 while (iterator.hasNext()){
7         System.out.println(iterator.next().toJson());
8 }

  指定文字搜尋選項

1 // 例如,以下文字搜尋指定對單詞cafe執行文字搜尋時的文字搜尋語言選項:
2 long matchCountEnglish = collection.countDocuments(Filters.text("cafe", new TextSearchOptions().language("english")));
3 System.out.println("Text search matches (english): " + matchCountEnglish);

8.網格FS

官方描述:

  • GridFS是用於儲存和檢索超出BSON文件大小限制16MB的檔案的規範。
  • GridFS不會將檔案儲存在單個文件中,而是將檔案劃分為多個部分或大塊,並將每個大塊儲存為單獨的文件。
  • 查詢GridFS儲存中的檔案時,Java驅動程式將根據需要重新組裝塊。

 程式碼示例:

建立儲存桶

 1 public static void main(String[] args) {
 2  
 3      // 建立連線憑證
 4      // 使用者名稱
 5      String user = "mydb";
 6      // 資料來源
 7      String source = "mydb";
 8      // 密碼
 9      char[] password = "mydb".toCharArray();
10  
11      // 憑證設定
12      MongoCredential credential = MongoCredential.createCredential(user, source, password);
13  
14      // MongoClient 連線設定
15      MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
16              .applyToClusterSettings(builder ->
17                      builder.hosts(Arrays.asList(new ServerAddress("127.0.0.1"))))
18              .credential(credential)
19              .build();
20  
21      // 建立Mongo連線
22      MongoClient mongoClient = MongoClients.create(mongoClientSettings);
23  
24      // 選擇資料庫
25      MongoDatabase database = mongoClient.getDatabase("mydb");
26  
27      // GridFS將檔案儲存在兩個集合中:一個chunks集合儲存檔案塊,一個 files集合儲存檔案後設資料。這兩個集合位於公共儲存桶中,並且集合名稱以儲存桶名稱為字首。
28      // 第一次將資料上傳到GridFS儲存桶時,GridFS將在files和chunks集合上自動建立索引。
29      // Create a gridFSBucket using the default bucket name "fs"
30      // 使用預設的bucket名稱“fs”建立一個gridFSBucket
31      GridFSBucket gridFSBucket = GridFSBuckets.create(database);
32      
33     // 指定儲存桶名稱(建立儲存桶方式2)
34     // GridFSBucket gridFSFilesBucket = GridFSBuckets.create(database, "files");
35  
36 }

上傳檔案

UploadFromStream方式

  該GridFSBucket.uploadFromStream方法讀取an的內容InputStream並將其儲存到中GridFSBucket

 1 // 使用預設的bucket名稱“fs”建立一個gridFSBucket
 2     GridFSBucket gridFSBucket = GridFSBuckets.create(database);
 3 
 4     // UploadFromStream
 5     // Get the input stream
 6     // 獲取輸入流
 7     try {
 8         InputStream streamToUploadFrom = new FileInputStream(new File("D:\\ServiceInfoQuery.pdf"));
 9         // Create some custom options
10         // 建立一些自定義選項
11         GridFSUploadOptions options = new GridFSUploadOptions()
12                 .chunkSizeBytes(358400)
13                 .metadata(new Document("type", "presentation"));
14 
15         ObjectId fileId = gridFSBucket.uploadFromStream("mongodb-tutorial1", streamToUploadFrom, options);
16         streamToUploadFrom.close();
17         System.out.println("The fileId of the uploaded file is: " + fileId.toHexString());
18 
19     } catch (FileNotFoundException e) {
20         e.printStackTrace();
21     } catch (IOException e){
22         e.printStackTrace();
23     }

OpenUploadStream方式

  該GridFSUploadStream快取資料,直到它到達chunkSizeBytes,然後插入塊到chunks集合。GridFSUploadStream關閉時,最後的塊寫入和檔案後設資料插入到files集合。

 1     // 指定儲存桶名稱(建立儲存桶方式2)
 2     GridFSBucket gridFSFilesBucket = GridFSBuckets.create(database, "files");
 3 
 4     // OpenUploadStream
 5     GridFSUploadOptions options = new GridFSUploadOptions()
 6             .chunkSizeBytes(358400)
 7             .metadata(new Document("type", "presentation"));
 8 
 9     GridFSUploadStream uploadStream = gridFSFilesBucket.openUploadStream("mongodb-tutorial-2", options);
10 
11     try {
12         byte[] data = Files.readAllBytes(new File("D:\\gridfs.pdf").toPath());
13         uploadStream.write(data);
14         uploadStream.close();
15         System.out.println("The fileId of the uploaded file is: " + uploadStream.getObjectId().toHexString());
16     } catch (IOException e) {
17         e.printStackTrace();
18     }

查詢檔案

 1     Consumer<GridFSFile> printBlock = new Consumer<GridFSFile>() {
 2         @Override
 3         public void accept(GridFSFile gridFSFile) {
 4             System.out.println(gridFSFile.getFilename());
 5         }
 6     };
 7 
 8     // 查詢儲存在GridFS中的檔案
 9     // 列印出每個儲存檔案的檔名
10     gridFSBucket.find().forEach(printBlock);

下載檔案

  通過ObjectId下載

 1     // 從MongoDB中讀取內容,並將資料直接寫入提供的OutputStream
 2     // 通過ObjectId 下載
 3     try {
 4 
 5         FileOutputStream streamToDownloadTo = new FileOutputStream("/tmp/mongodb-tutorial3.pdf");
 6 
 7         ObjectId objectId = gridFSBucket.find().first().getObjectId();
 8 
 9         gridFSBucket.downloadToStream(objectId, streamToDownloadTo);
10 
11         streamToDownloadTo.close();
12 
13         System.out.println(streamToDownloadTo.toString());
14 
15     } catch (FileNotFoundException e) {
16         e.printStackTrace();
17     } catch (IOException e) {
18         e.printStackTrace();
19     }

  通過檔名下載

 1     // 通過 檔名 下載
 2     try {
 3         FileOutputStream streamToDownloadTo = new FileOutputStream("/tmp/mongodb-tutorial1.pdf");
 4         GridFSDownloadOptions downloadOptions = new GridFSDownloadOptions().revision(0);
 5     // 兩種方式選擇一種即可
 6         gridFSBucket.downloadToStream(gridFSBucket.find().first().getFilename(), streamToDownloadTo, downloadOptions);
 7         // gridFSBucket.downloadToStream("mongodb-tutorial", streamToDownloadTo, downloadOptions);
 8         streamToDownloadTo.close();
 9     } catch (FileNotFoundException e) {
10         e.printStackTrace();
11     } catch (IOException e) {
12         e.printStackTrace();
13     }

讀取檔案

  通過ObjectId讀取檔案

1     // 通過 ObjectId 讀取檔案
2     ObjectId objectId = gridFSBucket.find().first().getObjectId();
3     GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(objectId);
4     int fileLength = (int) downloadStream.getGridFSFile().getLength();
5     System.out.println("檔案長度" + fileLength);
6     byte[] bytesToWriteTo = new byte[fileLength];
7     downloadStream.read(bytesToWriteTo);
8     downloadStream.close();
9     System.out.println(new String(bytesToWriteTo, StandardCharsets.UTF_8));

  通過名稱讀取檔案

 1     // 通過名稱讀取檔案
 2     String filename = gridFSBucket.find().first().getFilename();
 3     GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(filename);
 4     int fileLength = (int) downloadStream.getGridFSFile().getLength();
 5     System.out.println("檔案長度" + fileLength);
 6     byte[] bytesToWriteTo = new byte[fileLength];
 7     downloadStream.read(bytesToWriteTo);
 8     downloadStream.close();
 9 
10     System.out.println(new String(bytesToWriteTo, StandardCharsets.UTF_8));

重新命名檔案

1     // 重新命名檔案
2     // 注意
3     // 該rename方法要求使用 ObjectId 而不是 filename 來確保重新命名正確的檔案。
4     // 要重新命名同一檔名的多個修訂,請首先檢索檔案的完整列表。然後對於每個應重新命名的檔案,然後rename使用相應的_id
5     ObjectId objectId = gridFSBucket.find().first().getObjectId();
6     gridFSBucket.rename(objectId, "test");

刪除檔案

1     // 刪除檔案
2     // ObjectId of a file uploaded to GridFS
3     // 上載到GridFS的檔案的ObjectId
4     ObjectId objectId = gridFSBucket.find().first().getObjectId();
5     gridFSBucket.delete(objectId);

四、總結

  總的來說,java操作MongoDB還是比較簡單的。

相關文章