user3003466
user3003466

Reputation: 323

Mongo document and gridfs file relationship

Currently there is a requirement there is a object - "application" which has the filed: "name", "uploadTime" and "executeFile".

Currently the database is mongodb. I want to use a document

Class Application {
     String id;
     String name;
     String type;
     Date uploadTime;
     GridFSDBFile executeFile;
}

The Dao layer, when I write save, I find I can not related GridFSDBfile to document directly. I need first use GridFsTemplate.store save GridDBFile, then use GridFsTemplate.findOne find it by name, and put the object nested in application document. Then use MongoOperation save the application document.

try {
        inputStream = new FileInputStream("C:/testing.app");
        gridFsOperations.store(inputStream, "test.app", "jar");

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    Query query = query(where("filename").is("test.app"));
    GridFSDBFile gridFsDBFile = gridFsOperations.findOne(query);

    Application application = new Application ();
    application.setName( "test-app");
    application.setType( "type", "Java");
    application.setexecuteFile (gridFsDBFile);

    applicationDao.save(application);

Is there any way to just call MongoOperation? If not, I think call GridFsTemplate.store and MongoOperation.save need executed in a transaction. I remember that Mongo doens't support transaction. How to do this? Only check the transaction in Java code?

Upvotes: 3

Views: 3201

Answers (1)

BatScream
BatScream

Reputation: 19700

I find I can not related GridFSDBfile to document directly. I need first use GridFsTemplate.store save GridDBFile, then use GridFsTemplate.findOne find it by name, and put the object nested in application document. Then use MongoOperation save the application document.

You got it wrong here. When you save a file in GridFS, the storage of the file and its metadata are distributed across two collections namely, fs.files and fs.chunks. Whenever a file is inserted using the GridFs API, the file and its metadata are stored at a single shot.

To give a better picture,

When the below instruction is executed:

    gridFsOperations.store(inputStream, "test.app", "jar");

MongoDB makes two entries, one into the fs.files and the other to the fs.chunks collections.

one entry is made into the fs.files collection:

{
        "_id" : ObjectId("545d6699756c779b8cb8b13d"),
        "type":"jar",
        "filename" : "test.app",
        "aliases" : null,
        "chunkSize" : NumberLong(262144),
        "uploadDate" : ISODate("2014-11-08T00:40:57.298Z"),
        "length" : NumberLong(433),
        "contentType" : null,
        "md5" : "5e49ad0614687c7ad343f6f9fe6843b2"
}

This entry has only the metadata information of the file, such as the file name and the type. You can even set other metadata information using the BasicDBObject class. You want to include the uploadTime,

DBObject metadata = new BasicDBObject();
metadata.put("uploadTime", Calendar.getInstance().getTime());

and save it as below,

gridFsOperations.store(inputStream, "test.app", "jar",metadata );

Also it has one piece of crucial information, i.e the reference to the document which contains the actual file content, in its _id field.

Another entry is made into the fs.chunks collection:

{
        "_id" : ObjectId("545d6699756c779b8cb8b13e"),
        "files_id" : ObjectId("545d6699756c779b8cb8b13d"),
        "n" : 0,
        "data" : BinData(0,"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4N
Cjx4c2w6c3R5bGVzaGVldCB4bWxuczp4c2w9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5z
Zm9ybSINCnZlcnNpb249IjEuMCI+DQoNCjx4c2w6b3V0cHV0IGVuY29kaW5nPSJVVEYtOCIgbWV0aG9k
PSJ4bWwiIGluZGVudD0ieWVzIi8+DQo8eHNsOnZhcmlhYmxlIG5hbWU9InRvcExldmVsIj4NCiAgICAg
ICAgPHhzbDp2YXJpYWJsZSBuYW1lPSJpbm5lciIgc2VsZWN0PSInSGknIiAvPg0KICAgICAgICA8eHNs
OnZhbHVlLW9mIHNlbGVjdD0iJGlubmVyIi8+DQo8L3hzbDp2YXJpYWJsZT4NCiAgICANCjx4c2w6dGVt
cGxhdGUgbWF0Y2g9Ii8iID4NCiAgICA8eHNsOnZhbHVlLW9mIHNlbGVjdD0iJHRvcExldmVsIiAvPg0K
PC94c2w6dGVtcGxhdGU+DQo8L3hzbDpzdHlsZXNoZWV0Pg==")
} 

This is the actual document, that contains the file content in its Binary form. Take a note of the document's files_id field. It has the same ObjectId as referenced from the entry in fs.files collection.

This is how MongoDB maintains the relationship between the file content and its metadata. GridFS is a mere API to abstract the user from handling the low level implementation.

f not, I think call GridFsTemplate.store and MongoOperation.save need executed in a transaction. I remember that Mongo doens't support transaction. How to do this? Only check the transaction in Java code?

There is no need for the application to create or maintain any transactions for this operation.

Upvotes: 3

Related Questions