Spring Доступны данные + MongoDB GridFS через репозиторий?

Недавно я обнаружил GridFS, который я хотел бы использовать для хранения файлов с метаданными. Я просто задавался вопросом, можно ли использовать MongoRepository для запроса GridFS? Если да, может ли кто-нибудь дать мне пример?

Я бы тоже принял решение, используя Hibernate, если есть.

Причина в том, что: Мои метаданные содержат много разных полей, и было бы намного проще запросить репозиторий, чем написать некоторые new Query(Criteria.where(...)) для каждого сценария. И я надеюсь, вы также можете просто взять объект Java и предоставить его через REST API без самого файла.

EDIT: я использую

  • Spring 4 Beta​​li >
  • Spring Данные Mongo 1.3.1
  • Hibernate 4.3 Beta​​li >

Ответы

Ответ 1

Есть способ решить эту проблему:

@Document(collection="fs.files")
public class MyGridFsFile {

    @Id
    private ObjectId id;
    public ObjectId getId() { return id; }

    private String filename;
    public String getFilename() { return filename; }

    private long length;
    public long getLength() { return length; }

    ...

}

Для этого вы можете написать обычный Spring Mongo Repo. Теперь вы можете, по крайней мере, запросить коллекцию fs.files, используя Spring Data Repo. Но. Таким образом вы не можете получить доступ к содержимому файла.

Для получения самого содержимого файла у вас есть (по крайней мере) 2 варианта:

  • Используйте file = gridOperations.findOne(Query.query(Criteria.where("_id").is(id))); InputStream is = file.getInputStream();

  • Посмотрите исходный код GridFSDBFile. Там вы можете увидеть, как он внутренне запрашивает коллекцию fs.chunks и заполняет InputStream.

(Вариант 2 действительно низкий уровень, вариант 1 намного проще, и этот код поддерживается разработчиками MongoDB-Java-Driver, хотя вариант 1 был бы моим выбором).


Обновление записей GridFS:

  • GridFS не предназначен для обновления содержимого файла!
  • Может быть полезно только обновление поля metadata. Остальные поля являются статичными.

Вы должны просто использовать свой собственный метод MyGridFsFileRepo update. Я предлагаю только создать сеттер для поля metadata.


Различные метаданные для разных файлов:

Я решил это с помощью класса abstract MyGridFsFile с общими метаданными, то есть:

@Document(collection="fs.files")
public abstract class AbstractMyGridFsFile<M extends AbstractMetadata> {

    ...

    private M metadata;
    public M getMetadata() { return metadata; }
    void setMetadata(M metadata) { this.metadata = metadata; }

}

И, конечно же, каждый impl имеет собственный AbstractMetadata impl. Что я сделал? AbstractMetadata всегда имеет поле, называемое type. Таким образом, я могу найти правильный AbstractMyGridFsFile impl. Хотя у меня также есть общий абстрактный репозиторий.

Btw: Тем временем я переключился сюда с помощью Spring Repo, чтобы использовать простой доступ через MongoTemplate, например:

protected List<A> findAll(Collection<ObjectId> ids) {
    List<A> files = mongoTemplate.find(Query.query(Criteria
            .where("_id").in(ids)
            .and("metadata.type").is(type) // this is hardcoded for each repo impl
    ), typeClass); // this is the corresponding impl of AbstractMyGridFsFile
    return files;
}

Надеюсь, это поможет. Я могу написать больше, если вам нужна дополнительная информация об этом. Просто скажи мне.

Ответ 2

Вы можете создать объект GridFS с базой данных из вашего MongoTemplate и затем взаимодействовать с этим:

MongoTemplate mongoTemplate = new MongoTemplate(new Mongo(), "GetTheTemplateFromSomewhere");
GridFS gridFS = new GridFS(mongoTemplate.getDb());

Объект GridFS позволяет создавать, удалять и находить и т.д.