Overview
This guide will help you successfully migrate your Ditto Kotlin Android application from the legacy query builder APIs to the modern DQL (Ditto Query Language). After reviewing this documentation, you’ll understand how to convert method chaining patterns to DQL syntax and systematically update your data operations.AI Agent Prompt
Use this prompt when working with an AI coding assistant to migrate your Ditto Kotlin Android app from legacy query builder to DQL.Copy AI Migration Prompt (Click to Expand)
Copy AI Migration Prompt (Click to Expand)
Key API Changes Reference
Query Syntax Migration
Legacy Query Builder → DQL Query SyntaxData Operations Migration
Legacy Query Builder → DQL Insert OperationsDocument Field Access Migration
Legacy Query Builder → Modern Field AccessObserver Migration
Legacy Query Builder → DQL Store Observer MigrationSync Subscriptions Migration
Legacy Query Builder → DQL Sync Subscriptions Subscribe with QueryCounter Type Migration
PN_COUNTER is the DQL equivalent of the legacy
DittoCounter type. When migrating counter operations from the legacy query builder’s .counter?.increment() method, use PN_INCREMENT BY in the APPLY clause. This maintains full compatibility with existing counter data created by DittoCounter.Attachment Operations with DQL
Attachment Creation and StoragePerformance Enhancements
Indexes for Improved Query Performance
DQL observers and queries benefit significantly from proper indexing. When migrating from the legacy query builder to DQL, creating indexes on frequently queried fields is essential for maintaining optimal performance. Why Indexes Matter for DQL:- DQL observers support advanced features like aggregates and projections
- These advanced features require full database scans to ensure consistent results
- Indexes dramatically reduce query execution time by avoiding full scans
- Combining indexes with observers provides better performance than legacy query builder
- Create indexes on fields used in
WHEREclauses - Create indexes before registering observers for those queries
- Use compound indexes for queries with multiple filter conditions
- Monitor query performance and add indexes as needed
Common Pitfalls to Avoid
1. DQL Syntax Errors
Use:paramName for parameters, not $0 or string interpolation.
2. Missing Parameter Binding
NEVER use string interpolation in queries. Always use parameterized queries withMap<String, Any>.
3. Counter Type Errors
UseCOUNTER annotation in collection definitions. Do NOT use SET with COUNTER fields. Use APPLY with PN_INCREMENT BY. Pass negative values for decrements.
4. Memory Management with Observers
TheDittoQueryResult passed to your handler — and every DittoQueryResultItem it
owns — is closed as soon as your lambda returns. Never return result.items
out of the lambda or store individual items in a field; doing so will throw
IllegalStateException: Query result item has already been closed. Use the
(result, diff) overload of registerObserver when you need a diff — the differ
is managed by the observer in v5; you do not construct one yourself.
5. Attachment Handling
UseATTACHMENT annotation in collection definitions. Create attachments with ditto.store.newAttachment().