Связь документа Mongo и файла gridfs

В настоящее время требуется наличие объекта - "приложение", которое имеет поля: "имя", "время загрузки" и "исполняемый файл".

В настоящее время база данных mongodb. Я хочу использовать документ

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

Слой Дао, когда я пишу сохранение, я обнаруживаю, что не могу напрямую связать файл GridFSDB с документом. Мне нужно сначала использовать GridFsTemplate.store, сохранить GridDBFile, затем использовать GridFsTemplate.findOne, найти его по имени и поместить объект, вложенный в документ приложения. Затем используйте MongoOperation, чтобы сохранить документ приложения.

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

Есть ли способ просто позвонить MongoOperation? Если нет, я думаю, вызов GridFsTemplate.store и MongoOperation.save необходимо выполнить в транзакции. Я помню, что Mongo не поддерживает транзакции. Как это сделать? Проверять транзакцию только в Java-коде?


person user3003466    schedule 07.11.2014    source источник


Ответы (1)


Я обнаружил, что не могу напрямую связать GridFSDBfile с документом. Мне нужно сначала использовать GridFsTemplate.store, сохранить GridDBFile, затем использовать GridFsTemplate.findOne, найти его по имени и поместить объект, вложенный в документ приложения. Затем используйте MongoOperation, чтобы сохранить документ приложения.

Вы ошиблись здесь. Когда вы сохраняете файл в GridFS, хранилище файла и его метаданных распределяется между двумя коллекциями, а именно fs.files и fs.chunks. Всякий раз, когда файл вставляется с помощью GridFs API, файл и его метаданные сохраняются одновременно.

Чтобы картинка была лучше,

При выполнении приведенной ниже инструкции:

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

MongoDB делает две записи: одну в коллекции fs.files, а другую в коллекции fs.chunks.

в сборник fs.files внесена одна запись:

{
        "_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"
}

Эта запись содержит только метаданные файла, такие как имя файла и тип. Вы даже можете установить другую информацию метаданных, используя класс BasicDBObject. Вы хотите включить uploadTime,

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

и сохраните его, как показано ниже,

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

Кроме того, в его поле _id есть одна важная информация, то есть ссылка на документ, содержащий фактическое содержимое файла.

В коллекцию fs.chunks внесена еще одна запись:

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

Это фактический документ, содержащий содержимое файла в форме Binary. Обратите внимание на поле files_id документа. Он имеет тот же ObjectId, на который ссылается запись в коллекции fs.files.

Вот как MongoDB поддерживает связь между содержимым файла и его метаданными. GridFS — это просто API для отвлечения пользователя от работы с низкоуровневой реализацией.

Если нет, я думаю, что вызовы GridFsTemplate.store и MongoOperation.save должны выполняться в транзакции. Я помню, что Mongo не поддерживает транзакции. Как это сделать? Проверять транзакцию только в коде Java?

Приложению не нужно создавать или поддерживать какие-либо транзакции для этой операции.

person BatScream    schedule 08.11.2014
comment
Я думаю, вы можете неправильно понять мою мысль. мой вопрос не в содержании файла, а в метаданных файла. Мой вопрос: у меня есть обычный документ, и в этом обычном документе есть элемент gridfs. Я хочу сохранить документ и каскадно сохранить элемент gridfs. В противном случае я должен сначала сохранить элемент gridfs, а затем сохранить документ вручную. Вы знаете, как каскадное сохранение? - person user3003466; 08.11.2014
comment
Вот где ты ошибаешься. Вы всегда можете запросить файл в коллекции fs.chunks. Нет смысла снова сохранять содержимое в другой коллекции. Вам нужно пересмотреть свой подход. - person BatScream; 08.11.2014
comment
@BatScream привет, не могли бы вы сказать, каким будет оптимизированный способ управления такими данными: User, file.files и file.chunks - это три коллекции, я хочу, чтобы конкретный пользователь со всеми связанными с ним файлами был в ответе, возможно ли это. ? {имя: batMan, электронная почта: [email protected], файлы: [{file1},{file2},{file3},.... и т. д.]} - person mfaisalhyder; 19.05.2016