使用GridFS进行文件版本控制

时间:2014-05-29 13:54:39

标签: mongodb gridfs spring-data-mongodb

我正在尝试使用GridFS在mongo DB中存储版本化内容。因此,我将一个版本字段添加到我正在存储的文件的元数据中。这一切都运作良好。现在我想在不知道版本的情况下获得最新版本。这里:Find the latest version of a document stored in 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()中,没有必要加载文件本身。

3 个答案:

答案 0 :(得分:1)

findOne只返回一个结果,更具体地说是与查询匹配的 first 一个结果。

我不太确定使用findOne时是否返回了最新版本。请尝试查找。

更加手动的方法是过滤结果集,查询最高版本值的文件名。

通常,版本字段仅显示文档更改的频率。它用于称为乐观锁定的东西,它通过检查文档的当前版本与更改的文档所具有的版本来工作。如果数据库中的版本高于要保存的文档中的版本,则另一个进程对文档进行了更改,并引发异常。

对于存储版本化文档,git(例如通过egit)可能是一种解决方案。

编辑:经过快速研究,以下是它的工作原理。应使用元数据中自动设置的上载日期完成文件版本控制。查询它,降序排序并使用第一个结果。您无需再手动设置版本。

答案 1 :(得分:0)

尝试向查询添加排序,如下所示:

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

一旦有了GridFSDBFile,就可以轻松检索元数据,而无需使用以下方法加载整个文件:

DBObject metadata = latestVersionRecord.getMetaData();

希望它有所帮助!

答案 2 :(得分:0)

我知道已经有一段时间了,因为这个问题已被提出,我不知道当时的代码是否相同,但我认为这些信息可能有助于未来的读者:

查看源代码会显示findOne completely ignores the sorting part defined in the query,而find actually makes use of it

因此,您需要使用find进行常规查询,然后选择找到的第一个对象(有关详细信息,请参阅Markus W Mahlberg's answer)。