Управление версиями файлов с помощью GridFS

Я пытаюсь сохранить версионный контент в базе данных mongo с помощью GridFS. Поэтому я добавляю поле версии в метаданные сохраняемого файла. Все это хорошо работает. Теперь я хочу получить последнюю версию, не зная версии. Здесь: Найдите последнюю версию сохраненного документа в MongoDB - GridFs кто-то упоминает, что findOne всегда возвращает самый молодой (самый последний) файл, если он соответствует запросу. Что есть, чего я хочу. Но когда я пытаюсь это сделать, я всегда получаю первый (самый старый) файл из findOne(). Я использую spring-data-mongodbверсию 1.5.0.RELEASE

Вот мой текущий код:

public void storeFileToGridFs(ContentReference contentReference, InputStream content) {
    Integer nextVersion = findLatestVersion(contentReference) + 1;
    DBObject metadata = new BasicDBObject();
    metadata.put("version", nextVersion);
    metadata.put("definitionId", contentReference.getContentDefinitionId());
    gridOperations.store(content, contentReference.getContentId().getValue(), metadata);
}

и найти последнюю версию:

private Integer findLatestVersion(ContentReference contentReference) {
    Query query = new Query(GridFsCriteria.whereFilename().is(contentReference.getContentId().getValue()));
    GridFSDBFile latestVersionRecord = gridOperations.findOne(query);
    if (latestVersionRecord != null) {
        Integer version = (Integer) latestVersionRecord.getMetaData().get("version");
        return version;
    } else return 0;
}

Но, как уже упоминалось, функция findLatestVersion() всегда возвращает 1 (кроме первого раза, когда она возвращает 0...

Если у меня это работает, есть ли способ получить только метаданные документа? В findLatestVersion() нет необходимости загружать сам файл.


person user1145874    schedule 29.05.2014    source источник


Ответы (3)


findOne возвращает ровно один результат, точнее первый результат в коллекции, соответствующий запросу.

Я не слишком уверен, возвращается ли последняя версия при использовании findOne. Попробуйте вместо этого найти.

Более ручным подходом будет фильтрация набора результатов по запросу имени файла для наибольшего значения версии.

Как правило, поле версии показывает только то, как часто документ изменялся. Он используется для чего-то, что называется оптимистической блокировкой, которая работает, сверяя текущую версию документа с той, которая есть в измененном документе. Если версия в базе данных выше, чем в сохраняемом документе, другой процесс внес изменения в документ и возникает исключение.

Для хранения версий документов решением может быть git (например, через egit).

РЕДАКТИРОВАТЬ: После быстрого исследования, вот как это работает. Управление версиями файлов должно выполняться с использованием автоматически установленной даты загрузки из метаданных. Запросите его, отсортируйте по убыванию и используйте первый результат. Вам больше не нужно устанавливать версию вручную.

person Markus W Mahlberg    schedule 31.05.2014
comment
Спасибо за ваш ответ. Я не могу использовать Git или что-то еще, так как мы ограничены средой. Также я не могу использовать метку времени загрузки в качестве номера версии из-за обработки версий в окружающей системе. К сожалению, метаданные файлов хранятся в другом месте. Я думаю, мы должны изменить это в будущем. В настоящее время я использую ручной способ из вашего третьего абзаца. - person user1145874; 02.06.2014
comment
Egit — это чистая реализация Java, iirc. - person Markus W Mahlberg; 04.06.2014

Я знаю, что прошло некоторое время с тех пор, как этот вопрос был задан, и я не знаю, был ли код таким же, но я думаю, что эта информация может помочь будущим читателям:

Глядя на исходный код, видно, что findOne полностью игнорирует часть сортировки, определенную в запросе, а find на самом деле использует его.

Поэтому вам нужно сделать обычный запрос с помощью find, а затем выбрать первый найденный объект (см. Информация).

person Frozn    schedule 14.10.2016

Попробуйте добавить сортировку в запрос, например:

GridFSDBFile latestVersionRecord = template.findOne(
        new Query(GridFsCriteria.whereFilename().is(filename))
        .with(new Sort(Sort.Direction.DESC, "version")));

если у вас есть GridFSDBFile, вы можете легко получить метаданные без загрузки всего файла с помощью метода:

DBObject metadata = latestVersionRecord.getMetaData();

Надеюсь, поможет!

person Mateusz Błaż    schedule 20.06.2016