GridFS in Spring Data MongoDB – Spring Data MongoDB中的GridFS

最后修改: 2015年 10月 25日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This tutorial will explore one of the core features of Spring Data MongoDB: interacting with GridFS.

本教程将探讨Spring Data MongoDB的核心功能之一:与GridFS互动。

The GridFS storage spec is mainly used for working with files that exceed the BSON-document size limit of 16MB. And Spring Data provides a GridFsOperations interface and its implementation – GridFsTemplate – to easily interact with this filesystem.

GridFS存储规格主要用于处理超过BSON-文件大小限制16MB的文件。而Spring Data提供了一个GridFsOperations接口及其实现– GridFsTemplate,以方便与该文件系统进行交互。

2. Configuration

2.配置

2.1. XML Configuration

2.1.XML配置

Let’s start with the simple XML configuration for the GridFsTemplate:

让我们从GridFsTemplate的简单XML配置开始。

<bean id="gridFsTemplate" class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
    <constructor-arg ref="mongoDbFactory" />
    <constructor-arg ref="mongoConverter" />
</bean>

The constructor arguments to the GridFsTemplate include bean references to mongoDbFactory, which creates a Mongo database, and mongoConverter, which converts between Java and MongoDB types. Their bean definitions are below.

GridFsTemplate的构造参数包括对mongoDbFactorymongoConverter的bean引用,前者用于创建Mongo数据库,后者用于在Java和MongoDB类型之间进行转换。它们的豆类定义如下。

<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />

<mongo:mapping-converter id="mongoConverter" base-package="com.baeldung.converter">
    <mongo:custom-converters base-package="com.baeldung.converter"/>
</mongo:mapping-converter>

2.2. Java Configuration

2.2.Java配置

Let’s create a similar configuration, only with Java:

让我们创建一个类似的配置,只是用Java。

@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
public class MongoConfig extends AbstractMongoClientConfiguration {
    @Autowired
    private MappingMongoConverter mongoConverter;

    @Bean
    public GridFsTemplate gridFsTemplate() throws Exception {
        return new GridFsTemplate(mongoDbFactory(), mongoConverter);
    }
    
    // ...
}

For this configuration, we used the mongoDbFactory() method and auto-wired the MappingMongoConverter defined in the parent class AbstractMongoClientConfiguration.

对于该配置,我们使用了mongoDbFactory() 方法,并自动连接了定义在父类AbstractMongoClientConfiguration中的MappingMongoConverter

3. GridFsTemplate Core Methods

3.GridFsTemplate核心方法

3.1. store

3.1.商店

The store method saves a file into MongoDB.

store方法将一个文件保存到MongoDB。

Suppose we have an empty database and wish to store a file in it:

假设我们有一个空的数据库,希望在其中存储一个文件。

InputStream inputStream = new FileInputStream("src/main/resources/test.png"); 
gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).toString();

Note that we can save additional metadata along with the file by passing a DBObject to the store method. For our example, the DBObject might look something like this:

注意,我们可以通过向store方法传递一个DBObject来保存额外的元数据。对于我们的例子,DBObject可能看起来像这样。

DBObject metaData = new BasicDBObject();
metaData.put("user", "alex");

GridFS uses two collections to store the file metadata and its content. The file’s metadata is stored in the files collection, and the file’s content is stored in the chunks collection. Both collections are prefixed with fs.

GridFS使用两个集合来存储文件元数据和其内容。文件的元数据存储在files集合中,而文件的内容则存储在chunks集合。这两个集合的前缀是fs

If we execute the MongoDB command db[‘fs.files’].find(), we will see the fs.files collection:

如果我们执行MongoDB命令db[‘fs.files’].find(),我们将看到fs.files集合。

{
    "_id" : ObjectId("5602de6e5d8bba0d6f2e45e4"),
    "metadata" : {
        "user" : "alex"
    },
    "filename" : "test.png",
    "aliases" : null,
    "chunkSize" : NumberLong(261120),
    "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
    "length" : NumberLong(855),
    "contentType" : "image/png",
    "md5" : "27c915db9aa031f1b27bb05021b695c6"
}

The command db[‘fs.chunks’].find() retrieves the file’s content:

命令db[‘fs.chunks’].find() 检索文件的内容。

{
    "_id" : ObjectId("5602de6e5d8bba0d6f2e45e4"),
    "files_id" : ObjectId("5602de6e5d8bba0d6f2e45e4"),
    "n" : 0,
    "data" : 
    { 
        "$binary" : "/9j/4AAQSkZJRgABAQAAAQABAAD/4QAqRXhpZgAASUkqAAgAAAABADEBAgAHAAAAGgAAAAAAAABHb29nbGUAAP/bAIQAAwICAwICAwMDAwQDAwQFCAUFBAQFCgcHBggM
          CgwMCwoLCw0OEhANDhEOCwsQFhARExQVFRUMDxcYFhQYEhQVFAEDBAQGBQUJBgYKDw4MDhQUFA8RDQwMEA0QDA8VDA0NDw0MDw4MDA0ODxAMDQ0MDAwODA8MDQ4NDA0NDAwNDAwQ/8AA
          EQgAHAAcAwERAAIRAQMRAf/EABgAAQEBAQEAAAAAAAAAAAAAAAgGBwUE/8QALBAAAgEDAgQFAwUAAAAAAAAAAQIDBAURBiEABwgSIjFBYXEyUYETFEKhw
          f/EABoBAAIDAQEAAAAAAAAAAAAAAAMEAQIFBgD/xAAiEQACAgEDBAMAAAAAAAAAAAAAAQIRAyIx8BJRYYETIUH/2gAMAwEAAhEDEQA/AHDyq1Bb6GjFPMAszLkZHHCTi1I6O
          cXOFRZ1ZqoX6aqzRClkhb9MGVh2SsNyVI/hjG5389tuGcUaLK1GmFfpn5r3rnXpfV82pGtS3a0XmaGOO3zguKV1SWDwBQDH2uUWTOWMZzuM8bS0VQtJKRb2li9LL3l+4VNQPEfQTOB/WO
          G1K0JtUzwad1eZaYBiqzL4S2N8cZUsa7DqlRGdWvMq5aX6b9Tvb5pIZbggt7VcU3YacSkDbfuLNuu3lkk+98GNfIrLt2gK9K/NWl5Z87Ldebj3R0NTa2tVVKhOI0KoQ5AG4DRqSPk+gHGn
          khUPYNOx92vW9PcrdDW0FUJqOp7po5ETIYMxOdyOAK0qAvcgKPWa0oMTo7SEYDKPp98/5wPoJsx3rZ1wLhojS9iinLD9w9W47iSwVe0Z3wfrPoce2eC4I6rCX9MxrpUpWqudNunUosNLR1EkiyIGDqUKF
          fyZB+AeG80riueQdVfObC/tN1pLdaLfSxMiRQ08aIg2CjtGAB9uEyCSqSWujICUXwghT57A5+ePEoMvUdc5a3XlSsgUhZGjGM/TGAqjz+SfuT7DDmGC6WzzeyOv0+2amOrr3KylzTUwjjDeWGbJJ9/COI
          yvRFFv1iRsVGDaqYGWVsIoBZydsDhQGf/Z", 
        "$type" : "00" 
    }
}

3.2. findOne

3.2.findOne

findOne returns exactly one document that satisfies the specified query criteria.

findOne精确地返回一个满足指定查询条件的文档。

String id = "5602de6e5d8bba0d6f2e45e4";
GridFSFile gridFsFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(id)));

The code above will return the result record which was added in the example above. If the database contained more than one record which matched the query, it would return only one document. The specific record returned would be selected according to natural ordering (the order in which the documents were stored in the database).

上面的代码将返回上面例子中添加的结果记录。如果数据库中包含不止一条与查询相匹配的记录,它将只返回一个文档。返回的具体记录将根据自然排序(文档在数据库中的存储顺序)来选择。

3.3. find

3.3.找到

find selects documents from a collection and returns a cursor to the selected documents.

find从一个集合中选择文件,并返回一个光标到所选的文件。

Suppose we have the following database, containing 2 records:

假设我们有以下数据库,包含2条记录。

[
    {
        "_id" : ObjectId("5602de6e5d8bba0d6f2e45e4"),
        "metadata" : {
            "user" : "alex"
        },
        "filename" : "test.png",
        "aliases" : null,
        "chunkSize" : NumberLong(261120),
        "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
        "length" : NumberLong(855),
        "contentType" : "image/png",
        "md5" : "27c915db9aa031f1b27bb05021b695c6"
    },
    {
        "_id" : ObjectId("5702deyu6d8bba0d6f2e45e4"),
        "metadata" : {
            "user" : "david"
        },
        "filename" : "test.png",
        "aliases" : null,
        "chunkSize" : NumberLong(261120),
        "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
        "length" : NumberLong(855),
        "contentType" : "image/png",
        "md5" : "27c915db9aa031f1b27bb05021b695c6"
    }
]

If we use the GridFsTemplate to execute the following query:

如果我们使用GridFsTemplate来执行以下查询。

List<GridFSFile> fileList = new ArrayList<GridFSFile>();
gridFsTemplate.find(new Query()).into(fileList);

The resulting list should contain two records since we provided no criteria.

由于我们没有提供任何标准,结果列表应该包含两条记录。

We can, of course, provide some criteria for the find method. For example, if we would like to get files whose metadata contains users with name alex, the code would be:

当然,我们可以为find方法提供一些标准。例如,如果我们想获得元数据中包含名字为alex的用户的文件,代码将是。

List<GridFSFile> gridFSFiles = new ArrayList<GridFSFile>();
gridFsTemplate.find(new Query(Criteria.where("metadata.user").is("alex"))).into(gridFSFiles);

The resulting list will contain only one record.

由此产生的列表将只包含一条记录。

3.4. delete

3.4.删除

delete removes documents from a collection.

delete从一个集合中删除文件。

Using the database from the previous example, suppose we have the code:

使用前面例子中的数据库,假设我们有这样的代码。

String id = "5702deyu6d8bba0d6f2e45e4";
gridFsTemplate.delete(new Query(Criteria.where("_id").is(id)));

After executing delete, only one record remains in the database:

执行delete后,数据库中只剩下一条记录。

{
    "_id" : ObjectId("5702deyu6d8bba0d6f2e45e4"),
    "metadata" : {
        "user" : "alex"
    },
    "filename" : "test.png",
    "aliases" : null,
    "chunkSize" : NumberLong(261120),
    "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
    "length" : NumberLong(855),
    "contentType" : "image/png",
    "md5" : "27c915db9aa031f1b27bb05021b695c6"
}

with chunks:

有大块的。

{
    "_id" : ObjectId("5702deyu6d8bba0d6f2e45e4"),
    "files_id" : ObjectId("5702deyu6d8bba0d6f2e45e4"),
    "n" : 0,
    "data" : 
    { 
        "$binary" : "/9j/4AAQSkZJRgABAQAAAQABAAD/4QAqRXhpZgAASUkqAAgAAAABADEBAgAHAAAAGgAAAAAAAABHb29nbGUAAP/bAIQAAwICAwICAwMDAwQDAwQFCAUFBAQFCgcHBggM
          CgwMCwoLCw0OEhANDhEOCwsQFhARExQVFRUMDxcYFhQYEhQVFAEDBAQGBQUJBgYKDw4MDhQUFA8RDQwMEA0QDA8VDA0NDw0MDw4MDA0ODxAMDQ0MDAwODA8MDQ4NDA0NDAwNDAwQ/8AA
          EQgAHAAcAwERAAIRAQMRAf/EABgAAQEBAQEAAAAAAAAAAAAAAAgGBwUE/8QALBAAAgEDAgQFAwUAAAAAAAAAAQIDBAURBiEABwgSIjFBYXEyUYETFEKhw
          f/EABoBAAIDAQEAAAAAAAAAAAAAAAMEAQIFBgD/xAAiEQACAgEDBAMAAAAAAAAAAAAAAQIRAyIx8BJRYYETIUH/2gAMAwEAAhEDEQA/AHDyq1Bb6GjFPMAszLkZHHCTi1I6O
          cXOFRZ1ZqoX6aqzRClkhb9MGVh2SsNyVI/hjG5389tuGcUaLK1GmFfpn5r3rnXpfV82pGtS3a0XmaGOO3zguKV1SWDwBQDH2uUWTOWMZzuM8bS0VQtJKRb2li9LL3l+4VNQPEfQTOB/WO
          G1K0JtUzwad1eZaYBiqzL4S2N8cZUsa7DqlRGdWvMq5aX6b9Tvb5pIZbggt7VcU3YacSkDbfuLNuu3lkk+98GNfIrLt2gK9K/NWl5Z87Ldebj3R0NTa2tVVKhOI0KoQ5AG4DRqSPk+gHGn
          khUPYNOx92vW9PcrdDW0FUJqOp7po5ETIYMxOdyOAK0qAvcgKPWa0oMTo7SEYDKPp98/5wPoJsx3rZ1wLhojS9iinLD9w9W47iSwVe0Z3wfrPoce2eC4I6rCX9MxrpUpWqudNunUosNLR1EkiyIGDqUKF
          fyZB+AeG80riueQdVfObC/tN1pLdaLfSxMiRQ08aIg2CjtGAB9uEyCSqSWujICUXwghT57A5+ePEoMvUdc5a3XlSsgUhZGjGM/TGAqjz+SfuT7DDmGC6WzzeyOv0+2amOrr3KylzTUwjjDeWGbJJ9/COI
          yvRFFv1iRsVGDaqYGWVsIoBZydsDhQGf/Z", 
        "$type" : "00" 
    }
}

3.5. getResources

3.5.getResources

getResources returns all GridFsResource with the given file name pattern.

getResources返回所有具有给定文件名模式的GridFsResource

Suppose we have the following records in the database:

假设我们在数据库中有以下记录。

[
   {
       "_id" : ObjectId("5602de6e5d8bba0d6f2e45e4"),
       "metadata" : {
           "user" : "alex"
       },
       "filename" : "test.png",
       "aliases" : null,
       "chunkSize" : NumberLong(261120),
       "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
       "length" : NumberLong(855),
       "contentType" : "image/png",
       "md5" : "27c915db9aa031f1b27bb05021b695c6"
   },
   {
       "_id" : ObjectId("5505de6e5d8bba0d6f8e4574"),
       "metadata" : {
           "user" : "david"
       },
       "filename" : "test.png",
       "aliases" : null,
       "chunkSize" : NumberLong(261120),
       "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
       "length" : NumberLong(855),
       "contentType" : "image/png",
       "md5" : "27c915db9aa031f1b27bb05021b695c6"
    },
    {
       "_id" : ObjectId("5777de6e5d8bba0d6f8e4574"),
       "metadata" : {
           "user" : "eugen"
       },
       "filename" : "baeldung.png",
       "aliases" : null,
       "chunkSize" : NumberLong(261120),
       "uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
       "length" : NumberLong(855),
       "contentType" : "image/png",
       "md5" : "27c915db9aa031f1b27bb05021b695c6"
    }
]

Now let’s execute getResources using a file pattern:

现在让我们使用文件模式执行getResources

GridFsResource[] gridFsResource = gridFsTemplate.getResources("test*");

This will return the two records whose file names begin with “test” (in this case, they are both named test.png).

这将返回文件名以 “test “开头的两条记录(在本例中,它们都被命名为test.png)。

4. GridFSFile Core Methods

4.GridFSFile核心方法

The GridFSFile API is quite simple as well:

GridFSFileAPI也很简单。

  • getFilename – gets the filename of the file
  • getMetaData – gets the metadata for the given file
  • containsField – determines if the document contains a field with the given name
  • get – gets a field from the object by name
  • getId – gets the file’s object ID
  • keySet – gets the object’s field names

5. Conclusion

5.结论

In this article we looked at the GridFS features of MongoDB, and how to interact with them using Spring Data MongoDB.

在这篇文章中,我们研究了MongoDB的GridFS功能,以及如何使用Spring Data MongoDB与之互动。

The implementation of all these examples and code snippets can be found in my github project.

所有这些例子和代码片段的实现可以在我的github项目找到。