1

at the moment I am developing a backend Server with Play 2 Framework using Scala. I have the following problem:

I save documents like images in MongoDB using the File Handler GridFS. GridFs creates two files:

fs.files, which contains metadata and fs.chunks, which stores the chunks

But I would like to save the images in my own collection. All images should have an database entry like username and comments. I have two ideas how to solve the problem but I am in need of help.

Solution #1:

Use my own collection :

{
   username: String
   comments: Array<String>
   image   : Gridfs 
}

How to get the image in my own collection using GridFS? Is it possible?

Solution #2:

I use the fs.files collection, which contain the metadata and add the entries username and comments. I have tried it out, but it doesn't work.

Who might be able to assist me?

Thanks

i.am.michiel
  • 10,281
  • 7
  • 50
  • 86
masterWN
  • 85
  • 1
  • 9
  • How large will your image filesizes be? GridFS is a useful approach for storing very large files, but not essential if your images are less than the [maximum document size](http://docs.mongodb.org/manual/reference/limits/#BSON-Document-Size) (16MB as at MongoDB 2.6). You can consider storing images directly in a document as binary data (which sounds closer to what you are after with your suggested solutions). – Stennie Jan 20 '15 at 11:57
  • I can't say yet. Because I would like to store audio and videofiles, too. That's the reason why I would like to use gridfs. Videofiles will get more than 16MB – masterWN Jan 20 '15 at 14:55

1 Answers1

0

As for Solution #1

If you are using ReactiveMongo, there is an example project, with composite server response, consisting of files and json

https://github.com/sgodbillon/reactivemongo-demo-app/blob/master/app/controllers/Application.scala

 def showEditForm(id: String) = Action.async {
    val objectId = new BSONObjectID(id)
    // get the documents having this id (there will be 0 or 1 result)
    val futureArticle = collection.find(BSONDocument("_id" -> objectId)).one[Article]
    // ... so we get optionally the matching article, if any
    // let's use for-comprehensions to compose futures (see http://doc.akka.io/docs/akka/2.0.3/scala/futures.html#For_Comprehensions for more information)
    for {
      // get a future option of article
      maybeArticle <- futureArticle
      // if there is some article, return a future of result with the article and its attachments
      result <- maybeArticle.map { article =>
        import reactivemongo.api.gridfs.Implicits.DefaultReadFileReader
        // search for the matching attachments
        // find(...).toList returns a future list of documents (here, a future list of ReadFileEntry)
        gridFS.find(BSONDocument("article" -> article.id.get)).collect[List]().map { files =>
          val filesWithId = files.map { file =>
            file.id.asInstanceOf[BSONObjectID].stringify -> file
          }
          Ok(views.html.editArticle(Some(id), Article.form.fill(article), Some(filesWithId)))
        }
      }.getOrElse(Future(NotFound))
    } yield result
  }

You can use it as a reference implementation.

As for Solution #2

You should be able to store additional data in DefaultFileToSave.metadata, and query afterwards mongo with { "metadata.user" : "user"} (Look at Query on MongoDB GridFS metadata (Java))

Another Solution

Keep files & your meta information as independent entities, and manage them independently, it would be easier to extend them in future.

For GridFS upload functionality (https://github.com/ReactiveMongo/Play-ReactiveMongo)

def upload = Action(gridFSBodyParser(gridFS)) { request =>
  // here is the future file!
  val futureFile: Future[ReadFile[BSONValue]] = request.body.files.head.ref
  futureFile.map { file =>
    // do something
    Ok
  }.recover {
    case e: Throwable => InternalServerError(e.getMessage)
  }
}

To expand on previous, in terms of endpoints, as an example

  • /video/:id/file - your GridFS file endpoint
  • /video/:id/meta - your meta information endpoint (what ever you need it to be)
  • /video/:id (optional) - combined file & meta response.
Community
  • 1
  • 1
mavarazy
  • 7,562
  • 1
  • 34
  • 60
  • 1
    Thanks for your answer. I am using Play-ReactiveMongo with casbah. I can't find the position where the image is stored? As far as I know, in MongoDB joins are not supported. How can I keep files & meta information as independent entities? Can you give me some examples ? – masterWN Jan 19 '15 at 13:23