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", "www.onabai.com"); doc.setProperty("leitmotif", "Working on a cloud of documents!"); db.createDocument(doc); 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:
and the (last version of the) logo can be browsed in /db/document_id/attachment_name, in our case: /onabai/7f18cfd54dfa7372d0a7f79ae9002082/logo.
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", quote.getBytes()); 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:
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);
New Logo rev.: 4-a9c0fa53220eddd27b0b6d740219b961
and CouchDB Futton…
Showing that logo revpos is now 4 while quote revpos is still 3.
The logo in the browser is
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, "7f18cfd54dfa7372d0a7f79ae9002082"); // Add extra property doc.setProperty("author", "OnaBai"); db.updateDocument(doc); System.out.printf("New Document rev.: %s\n", doc.getRevision());
and CouchDB Futton displays the document with the additional property author.
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.
// Retrieve the document with the desired id BaseDocument doc = new BaseDocument(); doc.setId("7f18cfd54dfa7372d0a7f79ae9002082"); doc.setRevision("5-e613b877d4ce0382104c5cf1c1f078fa"); // Assign value to property doc.setProperty("author", "OnaBai"); db.updateDocument(doc); System.out.printf("New Document rev.: %s\n", doc.getRevision());
makes disappear all properties but author.