Перейти к основному содержимому

GridFS в Spring Data MongoDB

· 5 мин. чтения

1. Обзор

В этом руководстве будет рассмотрена одна из основных функций Spring Data MongoDB: взаимодействие с GridFS .

Спецификация хранилища GridFS в основном используется для работы с файлами, размер которых превышает предельный размер документа BSON , равный 16 МБ. А Spring Data предоставляет интерфейс GridFsOperations и его реализацию — GridFsTemplate — для простого взаимодействия с этой файловой системой.

2. Конфигурация

2.1. XML-конфигурация

Начнем с простой конфигурации XML для GridFsTemplate :

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

Аргументы конструктора для GridFsTemplate включают ссылки bean-компонента на mongoDbFactory , который создает базу данных Mongo, и mongoConverter , который выполняет преобразование между типами Java и MongoDB. Их определения бобов приведены ниже.

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

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

2.2. Конфигурация Java

Создадим аналогичную конфигурацию, только с Java:

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

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

// ...
}

Для этой конфигурации мы использовали метод mongoDbFactory() и автоматически подключили M appingMongoConverter, определенный в родительском классе AbstractMongoClientConfiguration .

3. Основные методы GridFsTemplate

3.1. хранить

Метод store сохраняет файл в MongoDB.

Предположим, у нас есть пустая база данных и мы хотим сохранить в ней файл:

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

Обратите внимание, что мы можем сохранить дополнительные метаданные вместе с файлом, передав DBObject методу store . В нашем примере DBObject может выглядеть примерно так:

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

GridFS использует две коллекции для хранения метаданных файла и его содержимого. Метаданные файла хранятся в коллекции файлов , а содержимое файла хранится в коллекции фрагментов . Обе коллекции имеют префикс fs .

Если мы выполним команду 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"
}

Команда 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 возвращает ровно один документ, удовлетворяющий заданным критериям запроса.

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

Приведенный выше код вернет запись результата, которая была добавлена в приведенном выше примере. Если база данных содержит более одной записи, соответствующей запросу, будет возвращен только один документ. Возвращаемая конкретная запись будет выбрана в соответствии с естественным порядком (порядком, в котором документы хранились в базе данных).

3.3. найти

find выбирает документы из коллекции и возвращает курсор к выбранным документам.

Предположим, у нас есть следующая база данных, содержащая 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"
}
]

Если мы используем GridFsTemplate для выполнения следующего запроса:

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

Результирующий список должен содержать две записи, поскольку мы не указали никаких критериев.

Конечно, мы можем указать некоторые критерии для метода поиска . Например, если мы хотим получить файлы, метаданные которых содержат пользователей с именем alex , код будет таким:

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

Результирующий список будет содержать только одну запись.

3.4. Удалить

delete удаляет документы из коллекции.

Используя базу данных из предыдущего примера, предположим, что у нас есть код:

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

После выполнения 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"
}

с кусочками:

{
"_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 возвращает все GridFsResource с заданным шаблоном имени файла.

Предположим, у нас есть следующие записи в базе данных:

[
{
"_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" : "foreach"
},
"filename" : "foreach.png",
"aliases" : null,
"chunkSize" : NumberLong(261120),
"uploadDate" : ISODate("2015-09-23T17:16:30.781Z"),
"length" : NumberLong(855),
"contentType" : "image/png",
"md5" : "27c915db9aa031f1b27bb05021b695c6"
}
]

Теперь давайте выполним getResources , используя шаблон файла:

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

Это вернет две записи, имена файлов которых начинаются с «test» (в данном случае они оба называются test.png ).

4. Основные методы GridFSFile

API GridFSFile также довольно прост:

  • getFilename — получает имя файла
  • getMetaData — получает метаданные для данного файла
  • containsField — определяет, содержит ли документ поле с заданным именем
  • get — получает поле из объекта по имени
  • getId — получает идентификатор объекта файла
  • keySet — получает имена полей объекта

5. Вывод

В этой статье мы рассмотрели функции GridFS MongoDB и способы взаимодействия с ними с помощью Spring Data MongoDB.

Реализацию всех этих примеров и фрагментов кода можно найти в моем проекте на github .