Skip to main content

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.

Key API Changes Reference

Query Syntax Migration

Legacy Query Builder → DQL Query Syntax

Data Operations Migration

Legacy Query Builder → DQL Insert Operations
Legacy Query Builder → DQL Update Operations
Legacy Query Builder → DQL Delete Operations
Legacy Query Builder → DQL Eviction Operations

Document Field Access Migration

Legacy Query Builder → Modern Field Access
Legacy Query Builder → Modern Document Conversion

Observer Migration

Legacy Query Builder → DQL Store Observer Migration
Performance Consideration: DQL observers provide more advanced return results including aggregates and projections. This requires more database full scans to ensure consistent results compared to the legacy query builder.Use indexes on query fields to maintain and improve observer performance. Indexes ensure your observers remain functional with optimal query performance.
Best Practice: Create Indexes for Observer Queries
For more information on creating and managing indexes, see the DQL Indexing documentation.

Sync Subscriptions Migration

Legacy Query Builder → DQL Sync Subscriptions Subscribe with Query
Subscribe with Parameters
Multiple Subscriptions
Cancel Subscription
Subscribe to All Documents

Counter 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.
Counter Increment
Counter Decrement
Initialize Counter in Document
Multiple Counter Operations

Attachment Operations with DQL

Attachment Creation and Storage
Attachment Fetching

Performance 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
Creating Indexes:
Best Practices:
  1. Create indexes on fields used in WHERE clauses
  2. Create indexes before registering observers for those queries
  3. Use compound indexes for queries with multiple filter conditions
  4. Monitor query performance and add indexes as needed
For comprehensive information on indexing strategies, syntax, and best practices, see the DQL Indexing documentation.

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 with Map<String, Any>.

3. Counter Type Errors

Use COUNTER 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

The DittoQueryResult 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

Use ATTACHMENT annotation in collection definitions. Create attachments with ditto.store.newAttachment().