一、声明

  • 本文依赖于 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不对Snappy或Zstandard内置支持,因此驱动程序依赖现有的开源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还是比较简单的。

关于MongoDB的简单理解(二)--Java篇的更多相关文章

  1. 关于MongoDB的简单理解(三)--Spring Boot篇

    一.前言 Spring Boot集成MongoDB非常简单,主要为加依赖,加配置,编码. 二.说明 环境说明: JDK版本为15(1.8+即可) Spring Boot 2.4.1 三.集成步骤 3. ...

  2. 关于MongoDB的简单理解(一)--基础篇

    一.什么是MongoDB? MongoDB是一个基于分布式文件存储的文档数据库,旨在简化开发和扩展,为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之 ...

  3. android开发学习 ------- MongoDB数据库简单理解

    首先说一下MongoDB是什么? MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. MongoDB 是一个基于分布式文件存储的数据库. N ...

  4. 简单工厂模式-Java篇

    简单工厂模式就是考虑如何实例化对象的问题,就是说到底要实例化谁,将来会不会增加实例化对象,比如计算器类中增加开根元素,应该考虑用一个单独的类来创造实例的过程,这就是工厂.下面将利用计算器类举例,解释简 ...

  5. 数据库——MongoDB——>Java篇

         MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案.      MongoDB  是一个介于关系数据库和非关系数据库之间的产 ...

  6. 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制

    [原创]分布式之数据库和缓存双写一致性方案解析(三)   正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...

  7. MongoDB最简单的入门教程之三 使用Java代码往MongoDB里插入数据

    前两篇教程我们介绍了如何搭建MongoDB的本地环境: MongoDB最简单的入门教程之一 环境搭建 以及如何用nodejs读取MongoDB里的记录: MongoDB最简单的入门教程之二 使用nod ...

  8. Deep learning:四十二(Denoise Autoencoder简单理解)

    前言: 当采用无监督的方法分层预训练深度网络的权值时,为了学习到较鲁棒的特征,可以在网络的可视层(即数据的输入层)引入随机噪声,这种方法称为Denoise Autoencoder(简称dAE),由Be ...

  9. Java秒杀简单设计二:数据库表和Dao层设计

    Java秒杀简单设计二:数据库表Dao层设计 上一篇中搭建springboot项目环境和设计数据库表  https://www.cnblogs.com/taiguyiba/p/9791431.html ...

随机推荐

  1. 本地显示Linux服务器的GUI程序

    如果我们UI自动化脚本跑在 Linux 服务器环境上,这个时候我们是看不到界面的,如果不使用浏览器的无头模式,这个时候我们的程序就跑不起来了,如何在服务器环境不使用浏览器的无头模式下进行UI测试呢,我 ...

  2. python在线练习

    不管学习那门语言都希望能做出实际的东西来,这个实际的东西当然就是项目啦,不用多说大家都知道学编程语言一定要做项目才行. 这里整理了70个Python实战项目列表,都有完整且详细的教程,你可以从中选择自 ...

  3. springboot源码解析-管中窥豹系列之项目类型(二)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  4. Facetoprocess_program_design

    面向过程程序设计 程序:计算机用可理解可执行的命令的集合. 过程:问题解决的步骤. 方法(函数) 结构化程序设计的基础 一.方法三要素 1 功能: 实现的功能(单一).简单.易维护 2 参数: (传入 ...

  5. 意想不到,这个神奇的bug让我加班到深夜

    给大家分享一个近期解决的线上问题,起因是这样的,近期参与公司的一个项目,工程量很大,代码编写测试过后终于到了紧张的上线时刻. 项目上线 上线前照例忐忑不安了一番,因为工程量比较大,预估可能不会很顺利, ...

  6. LeetCode703 流中第k大的元素

    前言: 我们已经介绍了二叉搜索树的相关特性,以及如何在二叉搜索树中实现一些基本操作,比如搜索.插入和删除.熟悉了这些基本概念之后,相信你已经能够成功运用它们来解决二叉搜索树问题. 二叉搜索树的有优点是 ...

  7. Flutter 基础组件:输入框和表单

    前言 Material组件库中提供了输入框组件TextField和表单组件Form. 输入框TextField 接口描述 const TextField({ Key key, // 编辑框的控制器,通 ...

  8. ssh连接不上vmware虚拟机centos7.5

    在vmware中安装centos7.5后,手动设置IP地址192.168.1.5,发现主机ping不通虚拟机的IP,以下是我的解决办法 1.vmware设置选择仅主机模式 2.在主机查看vmnet1( ...

  9. docker基础总结

    搜索镜像docker search ubuntu 搜索ubuntu的Docker镜像 搜索结果单个单词ubuntu这样的镜像,被称为基础镜像或根镜像,这些基础镜像由 Docker 公司创建搜索结果ti ...

  10. JVM-Class文件的结构

    Class类文件的结构 Class文件是一株以8个字节为单位的二进制流.各个数据项目严格按照顺序紧凑的排列在文件之中,中间没有任何的分隔符,当遇到占用的空间大于8个字节时,会按照高位在前的方式进行分割 ...