1

I'm trying to store versioned content in mongo DB with GridFS. Therefore I add a version field to the metadata of the file I'm storing. This all works well. Now I want to get the latest version without knowing the version. Here: Find the latest version of a document stored in MongoDB - GridFs someone mentions that findOne always returns the youngest (latest) file if matching the query. What is, what I want. But when I try this, I always get the first (oldest) file from findOne(). I'm using spring-data-mongodbversion 1.5.0.RELEASE

Here my current code:

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);
}

and to find the latest version:

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;
}

But, as already mentioned, the findLatestVersion() always returns 1 (except the first time, when it returns 0...

If I have this running, is there a way to only retrieve the metadata of the document? In findLatestVersion()it's not necessary to load the file itself.

Community
  • 1
  • 1
user1145874
  • 959
  • 3
  • 13
  • 21

3 Answers3

1

findOne returns exactly one result, more specifically the first one in the collection matching the query.

I am not too sure whether the latest version is returned when using findOne. Please try find instead.

A more manual approach would be filtering a result set from querying for the file name for the highest value of version.

In general, the version field only shows how often a document was changed. It is used for something which is called optimistic locking, which works by checking the current version of a document against the one the changed document has. If the version in the database is higher than the one in the document to be saved, another process has made changes to the document and an exception is raised.

For storing versioned documents, git (via egit for example) might be a solution.

EDIT: After a quick research, here is how it works. File versioning should be done using the automatically set upload date from the metadata. Query for it, sort descending and use the first result. You do not need to set the version manually any more.

Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
  • Thank you for your answer. I cannot use Git or else, since we are restricted to the environment. Also I can't use the upload timestamp as the version number, due to version handling in the surrounding system. Unfortunately, we have the files meta data stored at a different location. I think, we should change this in the future. I currently use the manual way from your third paragraph. – user1145874 Jun 02 '14 at 09:35
  • Egit is a pure Java impl, iirc. – Markus W Mahlberg Jun 03 '14 at 21:09
1

I know it's been a while since this question has been asked and I don't know whether the code has been the same back then, but I think this information may help future readers:

Looking at the source code shows that findOne completely ignores the sorting part defined in the query, while find actually makes use of it.

So you need to make a normal query with find and then select the first object found (refer to Markus W Mahlberg's answer for more information).

Community
  • 1
  • 1
Frozn
  • 539
  • 1
  • 8
  • 17
0

Try adding sorting to the query, like this:

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

once you have the GridFSDBFile, you can easily retrieve metadata without loading whole file with the method:

DBObject metadata = latestVersionRecord.getMetaData();

Hope it helps!