Data Store CRUD
DELETE
this article provides an overview and how to instructions for deleting documents using the evict dql operation /#evicting data /#coordinating evictions docid\ wwulv5vobsrh7rrndyh5l docid\ wwulv5vobsrh7rrndyh5l evicting data the evict method, once invoked, immediately removes the specified document from the local ditto store, making it inaccessible by local queries for complete dql syntax, see docid\ kspbi9cshpdud0iyuow9e although the document you evicted is removed from the local ditto store, the document stored within remote ditto stores persists to prevent the evicted data from reappearing on the screen in a single flicker, make sure to stop subscriptions before you call evict ; otherwise, the subscription remains active and even if you reset the data in your end user environment, the evicted data momentarily reappears sample evict query await ditto store execute("evict from cars where id = '123'");ditto store execute("evict from cars where id = '123'")await ditto store execute("evict from cars where id = '123'");dittoqueryresult result = (dittoqueryresult) ditto store execute( "evict from cars where id = '123'", new continuation<>() { @nonnull @override public coroutinecontext getcontext() { return emptycoroutinecontext instance; } @override public void resumewith(@nonnull object o) { if (o instanceof result failure) { // handle failure } } } );ditto store executeasync("evict from cars where id = '123'");ditto get store() execute("evict from cars where id = '123'");let query result = ditto store() execute( "evict from cars where id = '123'", none, ) await?;await ditto store execute("evict from cars where id = '123'"); evicting multiple documents in a collection the evict operation functions based on a condition, allowing updates to multiple documents simultaneously for example, the following snippet, once executed, purges all blue cars stored in the local ditto store let result = await ditto store execute( "evict from cars where color = 'blue'"); result mutateddocumentids foreach() { print($0) }var result = ditto store execute("evict from cars where color = 'blue'") result mutateddocumentids() foreach { id > println(id) }const result = await ditto store execute( "evict from cars where color = 'blue'" ); console log(result mutateddocumentids());dittoqueryresult result = (dittoqueryresult) ditto store execute( "evict from cars where color = 'blue'", new continuation<>() { @nonnull @override public coroutinecontext getcontext() { return emptycoroutinecontext instance; } @override public void resumewith(@nonnull object o) { if (o instanceof result failure) { // handle failure } } } );var result = await ditto store executeasync( "evict from cars where color = 'blue'"); result mutateddocumentids foreach(id => console writeline(id));auto result = ditto get store() execute( "evict from cars where color = 'blue'"); for (documentid id result) { std cout << id to string(); }let query result = ditto store() execute( "evict from cars where color = 'blue'", none, ) await?; for id in query result iter() { println!("{}", id to string()); }await ditto store execute("evict from cars where color = 'blue'"); using evict with sync subscriptions if subscriptions are not properly managed prior to executing evictions, you may inadvertently disrupt the intended state, resulting in inconsistencies and unexpected behavior for example, if you have an active subscription for fetching 'blue' cars and you subsequently evict the document with the id '123456' that matches the replication query, connected peers reinstate it in your local ditto store in other words, without modifying the subscription first, peers in the mesh will replicate the evicted document back to the local peer that evicted it therefore we encourage careful management of subscriptions and evictions to remove documents with active subscriptions, you must first cancel the relevant subscription before calling the evict method timing subscriptions and evictions the frequency for removing locally stored documents depends on your app's use case to avoid the risk of depleting local storage capacity, consider evicting data frequently, such as once per day (if not more) to enhance offline datastore resiliency, you can implement app logic that allows your end users to choose which data to evict from their environments in addition, take a balanced approach when using the subscribe and evict methods consider the advantages and drawbacks of each method and use them as appropriate for specific needs and requirements key considerations for using subscription and eviction methods include use subscribe to sync more data across connected peers in the mesh; however, be mindful of potential increased network usage, which may degrade sync performance use evict to manage local storage capacity and improve performance by routinely purging data stored locally coordinating evictions if you want to indicate that a batch of documents are irrelevant and, although they are to be retained, should not sync across peers, add the issafetoevict field to the document property tree then, use a method to alert clients to flag any documents they consider irrelevant ditto document { " id" "abc123", "color" "red", "mileage" 40000, "issafetoevict" true, "createdat" "2023 05 22t22 24 24 217z" } to ensure that peers continue replicating documents that are considered relevant, incorporate issafetoevict == false into their sync subscription query this approach restricts replication only to documents that peers mark as 'true' for issafetoevict once flagged, the peers clear irrelevant documents from their caches, all the while normal transactional operations continues without interruption await ditto store execute("evict from cars where issafetoevict = true");ditto store execute("evict from cars where issafetoevict = true") await()ditto store execute("evict from cars where issafetoevict = true");dittoqueryresult result = (dittoqueryresult) ditto store execute( "evict from cars where issafetoevict = true", new continuation<>() { @nonnull @override public coroutinecontext getcontext() { return emptycoroutinecontext instance; } @override public void resumewith(@nonnull object o) { if (o instanceof result failure) { // handle failure } } } );ditto store executeasync( "evict from cars where issafetoevict = true");ditto get store() execute( "evict from cars where issafetoevict = true");let query result = ditto store() execute( "evict from cars where issafetoevict = true", none, ) await?;await ditto store execute("evict from cars where issafetoevict = true"); deleting attachments unlike documents, attachments cannot be explicitly deleted on their own instead, you modify the document containing the attachment token referencing it attachment data stored within the small peer ditto store is automatically garbage collected on a 10 minute cadence when no longer referenced currently, attachments can only be deleted by way of garbage collection the following table provides an overview of the various ways you can indirectly delete attachments approach description update update the document to remove the associated attachment token evict delete the entire document, including the associated attachment token, from the ditto store the storage mechanism small peers use to store data, including blob data, depends on the platform if running in the browser or a server based system, data is stored in its random access memory (ram) if running on a mobile device like an iphone, data is stored on its local filesystem referencing previously evicted documents once removed, you can reference the evicted document using the mutateddocumentids method on the result soft delete pattern if you need a data recovery option, instead of permanently removing the data from the local ditto store like evict , opt for a soft delete pattern a soft delete pattern is a way to flag data as inactive while retaining it for various requirements, such as archival evidence, reference integrity, prevention of potential data loss due to end user error, and so on adding a soft delete flag to add a soft delete pattern, set the isarchived field value to true ditto document { " id" "123", "color" "blue", "isarchived" true // add this field } querying non archived documents to query to monitor documents that are not archived, establish a live query where isarchived is set to false , and then construct your live query callback it's likely that the isarchived field is set lazily (i e has no value until it is true ), so you can use the coalesce() function to automatically return false if the value is unset t he following code demonstrates searching for documents that are unarchived let result = await ditto store execute(""" select from cars where coalesce(isarchived, false) = false """)var result = ditto store execute(""" select from cars where coalesce(isarchived, false) = false """)const result = await ditto store execute(` select from cars where coalesce(isarchived, false) = false` );dittoqueryresult result = (dittoqueryresult) ditto store execute( "select from cars where coalesce(isarchived, false) = false", new continuation<>() { @nonnull @override public coroutinecontext getcontext() { return emptycoroutinecontext instance; } @override public void resumewith(@nonnull object o) { if (o instanceof result failure) { // handle failure } } } );var result = await ditto store executeasync( "select from cars where coalesce(isarchived, false) = false");auto result = ditto get store() execute( "select from cars where coalesce(isarchived, false) = false");let query result = ditto store() execute( "select from cars where coalesce(isarchived, false) = false", none, ) await?;await ditto store execute(""" select from cars where coalesce(isarchived, false) = false """); removing soft delete flag to remove the flag and reactivate the document, set the isarchived field to false await ditto store execute(""" update cars set isarchived = false where id = '123' """)ditto store execute(""" update cars set isarchived = false where id = '123' """)await ditto store execute(` update cars set isarchived = false where id = '123'` );dittoqueryresult result = (dittoqueryresult) ditto store execute( "update cars set isarchived = false where id = '123'", new continuation<>() { @nonnull @override public coroutinecontext getcontext() { return emptycoroutinecontext instance; } @override public void resumewith(@nonnull object o) { if (o instanceof result failure) { // handle failure } } } );await ditto store executeasync(` "update cars set isarchived = false where id = '123'");ditto get store() execute( "update cars set isarchived = false where id = '123'");let query result = ditto store() execute( "update cars set isarchived = false where id = '123'", none, ) await?;await ditto store execute(""" update cars set isarchived = false where id = '123' """) removing data from big peer evict is not currently available for the big peer, although it's in development to learn more about removing data from your big peer instance, see docid\ jmhbyt6shuvf5rk8qgumv considerations to mitigate the risk of memory leaks, performance degradation, crashes, data loss, and, if applicable, reduced battery life, it is critical that you implement a thoughtful memory management strategy in your app depending on your use case, use either the evict method or apply the soft delete pattern to implement tools to help optimize memory usage in your app when planning your approach to memory management in your app, use the following criteria to help you during the decision making process consideration recommendation access frequency and relevance ensure memory is allocated only to the most relevant and frequently accessed documents by establishing an automatic process that evicts documents that are accessed less frequently no longer relevant or needed time based data establish an automatic process to evict or remove time based data older than a minimum of seven days (until expired, time based data remains accessible by way of local queries ) permanent data loss if documents are evicted from a local peer and don't exist on any other peer this data is lost and is unrecoverable access frequency and relevance considerations in peer to peer system design, there are technical tradeoffs between the amount of data synced across peers and the timeliness of access to synced data the greater the amount of data synced, the more timely offline read access becomes that is, database resilience in offline scenarios increases when more documents are being synced across distributed peers the fewer the number of documents replicated, the less the likelihood that peer devices run out of disk space and experience memory leaks, and the performance of the peer to peer mesh network that interconnects them degrades for considerations on using the evict and subscribe methods, see /#timing subscriptions and evictions