Working with attachments

Attachments in CouchDB are like attachments in an e-mail message.

Attachments might be considered as files with a content-type (its MIME type) and might be of any type: images (png, jpeg, gif, svg…), plain text, pdf, MS/Word, Excel…

Attachments have special treatment and not as “regular” properties of the document since they might be updated and retrieved but they cannot be queried: (so far) does not make sense query for images containing people smiling or music containing a C# minor played by a Stradivarius.

The easiest way for creating an attachment is create a document as I posted in here and then invoke createAttachment method from Database class.

Creating an attachment from a file

This example starts creating a BaseDocument with two properties called site and leitmotif and then creates an attachment called logo of type image/svg+xml. The method createAttachment has two interfaces, here we use one with an InputStream containing the attachment and its size as arguments.

// Create a BaseDocument
BaseDocument doc = new BaseDocument();
doc.setProperty("site", "");
doc.setProperty("leitmotif", "Working on a cloud of documents!");
System.out.printf("Id: %s rev.: %s\n", doc.getId(), doc.getRevision());

// Add attachment
File file = new File("resources/jcouchdb.svg");
InputStream is = new FileInputStream(file);
String rev = db.createAttachment(doc.getId(), doc.getRevision(),
                                 "logo", "image/svg+xml",
                                 is, file.length());
System.out.printf("New rev.: %s\n", rev);

The value returned by createAttachment is the new revision of the Document and the console output of the previous code is:

Id: 7f18cfd54dfa7372d0a7f79ae9002082 rev.: 1-f7d6c9a930283da1916cd9623bde99ab 
New rev.: 2-aecba701f8b643b71d28c50f83414705

an if we go to CouchDB Futton interface we will see:

Screen Shot 2012-05-08 at 10.57.23

and the (last version of the) logo can be browsed in /db/document_id/attachment_name, in our case: /onabai/7f18cfd54dfa7372d0a7f79ae9002082/logo.

Screen Shot 2012-05-08 at 11.16.31

Attachment storage in CouchDB

For a better understanding of what CouchDB Futton is displaying and how attachments work, it is interesting to get a little on details on how attachments are saved in CouchDB…

We can see the information of  the attachment that we have created (logo) is inside a JSON field called _attacments. For each attachment, we have one entry in _attachments containing the following fields:

  • content_type: the MIME type of the corresponding attachment.
  • revpos: revision (not the complete revision of the document but just the sequential part of therevision).
  • length: length / size of the attachment.
  • stub: denotes that this is not the complete attachment.

Creating an attachment from a byte[]

But attachments (as I said before) might be any MIME type… Here I create one of type plain/textand use the second interface of createAttachment where the attachment is sent in an argument as a byte[].

// Add another attachment
String quote = "It's all about the cloud. The fact of being always connected opens a whole new universe of possibilities. But whenever you design software for the cloud don't forget the sunny days where clouds are not visible.";
rev = db.createAttachment(doc.getId(), rev,
                          "quote", "text/plain", 
System.out.printf("Newer rev.: %s\n", rev);

And the output is:

Newer rev.: 3-08fb27a94de3081c6b61d9171c0aa077

where we can see the new revision and in CouchDB Futton we get:

Screen Shot 2012-05-08 at 11.21.11

Where we have two attachments: quote and logo. Pay attention to logo revpos that is 2 indicating the revision on which it has been created / updated, while logo revpos is in 3 since this was the version of the document when it was created / updated.

Updating an attachment

Lets change the logo image attached to our document.

// Update logo attachment
file = new File("resources/onabai-logo.gif");
is = new FileInputStream(file);
rev = db.updateAttachment(doc.getId(), rev,
                          "logo", "image/gif",
                          is, file.length());
System.out.printf("New Logo rev.: %s\n", rev);

The output…

New Logo rev.: 4-a9c0fa53220eddd27b0b6d740219b961

and CouchDB Futton…

Screen Shot 2012-05-08 at 11.32.37

Showing that logo revpos is now 4 while quote revpos is still 3.

The logo in the browser is

Screen Shot 2012-05-08 at 11.34.42

where we can see the new attachment. But since CouchDB is multi version, we can still get previous version in /db/document_id/attachment_name?rev=revision

If we update the document as in this code:

// Retrieve the document with the desired id
BaseDocument doc = db.getDocument(BaseDocument.class, 
// Add extra property
doc.setProperty("author", "OnaBai");
System.out.printf("New Document rev.: %s\n", doc.getRevision());

and CouchDB Futton displays the document with the additional property author.

Screen Shot 2012-05-08 at 11.48.00

IMPORTANT: Do not forget to read the document before updating it otherwise you will remove the content of it. CouchDB document storage is multi version but the content of an updated document is not merged with previous content.

This code:

// Retrieve the document with the desired id 
BaseDocument doc = new BaseDocument(); 
// Assign value to property 
doc.setProperty("author", "OnaBai"); 
System.out.printf("New Document rev.: %s\n", doc.getRevision());

makes disappear all properties but author.

Screen Shot 2012-05-08 at 11.51.06

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s