example - spring mongotemplate vs mongorepository
¿Es posible el acceso a Spring Data+MongoDB GridFS a través del repositorio? (2)
Recientemente descubrí GridFS que me gustaría usar para el almacenamiento de archivos con metadatos. Me pregunto si es posible usar un MongoRepository
para consultar GridFS. Si es así, ¿puede alguien darme un ejemplo?
También tomaría una solución usando Hibernate, si hay alguna.
El motivo es: Mis metadatos contienen muchos campos diferentes y sería mucho más fácil consultar un repositorio que escribir una new Query(Criteria.where(...))
para cada escenario. Y espero que también pueda tomar un objeto Java y proporcionarlo a través de la API REST sin el archivo en sí.
EDITAR: estoy usando
- Primavera 4 Beta
- Datos de primavera Mongo 1.3.1
- Hibernate 4.3 Beta
Hay una manera de resolver esto:
@Document(collection="fs.files")
public class MyGridFsFile {
@Id
private ObjectId id;
public ObjectId getId() { return id; }
private String filename;
public String getFilename() { return filename; }
private long length;
public long getLength() { return length; }
...
}
Puedes escribir un Spring Mongo Repo normal para eso. Ahora puede al menos consultar la colección fs.files
usando un fs.files
datos de Spring. Pero : No puede acceder al contenido del archivo de esta manera.
Para obtener el contenido del archivo, tienes (al menos) 2 opciones:
Use
file = gridOperations.findOne(Query.query(Criteria.where("_id").is(id)));
InputStream is = file.getInputStream();
Echa un vistazo al código fuente de
GridFSDBFile
. Allí puede ver, cómo consulta internamente la colecciónfs.chunks
y llena el InputStream.
(La opción 2 es realmente de bajo nivel, la opción 1 es mucho más fácil y este código es mantenido por los desarrolladores de MongoDB-Java-Driver, aunque la opción 1 sería mi elección).
Actualizando las entradas de GridFS:
- ¡GridFS no está diseñado para actualizar el contenido del archivo!
- Aunque solo actualizar el campo de
metadata
puede ser útil. El resto de los campos es algo estático.
Debería poder simplemente usar el método de update
personalizado de MyGridFsFileRepo
. Sugiero crear solo un setter para el campo de metadata
.
Diferentes metadatos para diferentes archivos:
abstract MyGridFsFile
esto utilizando una clase abstract MyGridFsFile
con metadatos genéricos, es decir:
@Document(collection="fs.files")
public abstract class AbstractMyGridFsFile<M extends AbstractMetadata> {
...
private M metadata;
public M getMetadata() { return metadata; }
void setMetadata(M metadata) { this.metadata = metadata; }
}
Y, por supuesto, cada impl tiene su propio AbstractMetadata
impl asociado. ¿Qué he hecho? AbstractMetadata
siempre tiene un campo llamado type
. De esta manera puedo encontrar el derecho AbstractMyGridFsFile
impl. Aunque también tengo un repositorio abstracto genérico.
Btw: Mientras tanto, cambié aquí de usar Spring Repo para usar el acceso sencillo a través de MongoTemplate
, como:
protected List<A> findAll(Collection<ObjectId> ids) {
List<A> files = mongoTemplate.find(Query.query(Criteria
.where("_id").in(ids)
.and("metadata.type").is(type) // this is hardcoded for each repo impl
), typeClass); // this is the corresponding impl of AbstractMyGridFsFile
return files;
}
Espero que esto ayude. Puedo escribir más, si necesitas más información sobre esto. Sólo dime.
Puedes crear un objeto GridFS con la base de datos desde tu MongoTemplate y luego interactuar con eso:
MongoTemplate mongoTemplate = new MongoTemplate(new Mongo(), "GetTheTemplateFromSomewhere");
GridFS gridFS = new GridFS(mongoTemplate.getDb());
El objeto GridFS te permite crear, eliminar y encontrar, etc.