Document Model
Data Types
ATTACHMENT
with the attachment data type, you can associate very large amounts of binary data, such as an image, video, a deeply embedded document, and so on, with a document and sync across peers without conflict unlike documents, attachments store data outside of the ditto store running locally in the end user environment and must be explicitly fetched to sync across distributed peers merge strategy last write wins the register and the attachment type follow the last write wins principle to determine the value that ultimately takes precedence and merges across distributed peers with this approach, each peer seeing the change will sequence it in the same order as every other peer, resulting in the same single value for example, one flight attendant updates a customer's seat number to 6 and another to seat 9 when the two conflicting versions merge, the edit with the highest timestamp wins put another way, by enforcing the last write wins merge strategy, for events a and b, where b is a result of a, event a always occurs before b described as unsurprising and meaningful , the last write wins strategy means that, rather than arbitrarily resolving all conflicting changes to some predefined value, the value that results and propagates across peers as the single source of truth both reflects the actual end user input and the update made by the last writer ensuring uninterrupted fetching maintain a strong reference to attachmentfetcher for the entirety of the asynchronous fetch operation by following these guidelines preserve the attachmentfetcher as a globally accessible instance prevent the fetch operation from silently aborting creating and fetching attachments the following snippet demonstrates a use case for leveraging the attachment , as well as the step by step process for creating and fetching the attachment if developing in swift, for a tutorial on how to work with an attachment in a chat app, see docid\ ilp1f4htvanuim5gk1d5t the following snippet demonstrates creating, associating, and fetching an attachment define a collection named 'foo' using base64 encoded image data and metadata, create an attachment object insert a document with an attachment in the collection later, retrieve the document by id and fetch the attachment using an attachmentfetcher //see the swift tutorial for implementing attachments in a chat app val testcontext = instrumentationregistry getinstrumentation() context val attachmentstream = testcontext assets open("attachment test png") val bitmapstream = testcontext assets open("attachment test png") val attachmentbitmap = bitmapfactory decodestream(bitmapstream) bitmapstream close() val metadata = mapof("name" to "my image png") val attachment = coll newattachment(attachmentstream, metadata) val docid = coll upsert(mapof("some" to "string", "my attachment" to attachment)) val doc = coll findbyid(docid) exec() val attachmenttoken = doc!!\["my attachment"] attachmenttoken val fetcher = coll fetchattachment(attachmenttoken!!) { when (it) { is completed > { val attbitmap bitmap = bitmapfactory decodestream(it attachment getinputstream()) } is progress > {} } }// define an image in base64 format const myimagebase64 = 'ivborw0kggoaaaansuheugaaaqaaaaeaaqmaaabmvdolaaaaa1bmvew10nbjbbbqaaaah0leqvroge3baq0aaadcopdpbq43oaaaaaaaaaaavg0haaabmmdh1qaaaabjru5erkjggg==' // convert the base64 data to a uint8array const myimagebytes = uint8array from(myimagebase64, (character) => character charcodeat(0)) // define metadata const metadata = { name 'image png' } // create an attachment object using the image data and metadata // on node, you can also pass a file path (string) instead of image data // and the attachment will be created from that file const attachment = await collection newattachment(myimagebytes, metadata) const docid = '123' const newdocument = { id docid, my attachment attachment } await ditto store execute(` insert into collection your collection name (my attachment attachment) documents (\ newdocument)`, { newdocument }) // later, find the document by id and then fetch the attachment const result = await ditto store execute(` select from your collection name where id = \ docid`, { docid }) const attachmenttoken = result\[0] items('my attachment') attachmenttoken // fetch the attachment const attachmentfetcher = collection fetchattachment(attachmenttoken, async (attachmentfetchevent) => { switch (attachmentfetchevent type) { case 'completed' const fetchedattachment = attachmentfetchevent attachment // do something with attachment break default console log('unable to fetch attachment') break } }) // there is also a more convenient way of fetching the attachment // (attachmentfetcher implements the `promiselike` protocol) const fetchedattachment = await collection fetchattachment(attachmenttoken) // do something with attachmentstring attachmentpath = tempfile getpath(); map\<string, string> metadata = new hashmap<>(); metadata put("name", "my image png"); dittoattachment attachment = coll newattachment(attachmentpath, metadata); tempfile delete(); map\<string, object> content = new hashmap<>(); content put("some", "string"); content put("my attachment", attachment); dittodocumentid docid = coll upsert(content); dittodocument doc = coll findbyid(docid) exec(); dittoattachmenttoken attachmenttoken = doc get("my attachment") getattachmenttoken(); dittoattachmentfetcher fetcher = coll fetchattachment(attachmenttoken, event > { if (event gettype() == dittoattachmentfetcheventtype completed) { dittoattachment att = event ascompleted() getattachment(); bufferedimage attachmentimage; try { attachmentimage = imageio read(att getinputstream()); } catch (ioexception e) { e printstacktrace(); } } else if (event gettype() == dittoattachmentfetcheventtype progress) { // do nothing wait for `completed` or `deleted` } else { } });string attachmentimagepath = path combine(directory getcurrentdirectory(), "attachment test png"); var originalbytes = file readallbytes(attachmentimagepath); var metadata = new dictionary\<string, string> { { "name", "my image png" } }; var attachment = coll newattachment(attachmentimagepath, metadata); string docid = "123"; var insertargs = new dictionary\<string, object>(); insertargs add( "newdocument", new { id = docid, myattachment = attachment }); await ditto store executeasync( "insert into your collection name documents (\ newdocument)", insertargs); var result = await ditto store executeasync( "select from your collection name where id = \ docid", new dictionary\<string, string> {{"docid", docid}}); var attachmenttoken = result items\[0] value\["my attachment"] attachmenttoken; using var fetcher = coll fetchattachment(attachmenttoken, ev => { switch (ev) { case dittoattachmentfetchevent completed e // do something with attachment break; default console writeline("unable to fetch attachment"); break; } });string attachmentimagepath = path combine(directory getcurrentdirectory(), "attachment test png"); var originalbytes = file readallbytes(attachmentimagepath); var metadata = new dictionary\<string, string> { { "name", "my image png" } }; var attachment = coll newattachment(attachmentimagepath, metadata); var docid = coll upsert(new dictionary\<string, object> { { "some", "string" }, { "my attachment", attachment } }); var doc = coll findbyid(docid) exec(); var attachmenttoken = doc\["my attachment"] attachmenttoken; using var fetcher = coll fetchattachment(attachmenttoken, ev => { switch (ev) { case dittoattachmentfetchevent completed e // do something with attachment break; default console writeline("unable to fetch attachment"); break; } });// to implement dart (beta) // coming soon