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 .