Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Indexes and queries

Fields marked @Index get an ObjectBox index, and the generator produces property descriptors (Message_, Contact_) for queries.

EntityIndexed fields
Messagehex, mailbox, uid, threadId, flags, receivedAt
Contacthex, emailIndex, phoneIndex
Mailboxhex
Outboxhex, action, created
Synctarget

Note on Sealed Columns: Personal text columns (Contact.name, Contact.email, Contact.phone, Contact.company, Contact.vcard, Message.subject, Message.preview, etc.) are sealed with AES-256-GCM under the Vault. They cannot be queried via plaintext database indexes. Exact lookups on contacts use keyed blind indexes (emailIndex, phoneIndex), and substring/autocomplete searches run in memory over decrypted rows.

Query examples

// A page of a mailbox, newest first
val query = messageBox.query(Message_.mailbox.equal(mailboxHex))
    .orderDesc(Message_.receivedAt)
    .build()
val page: List<Message> = query.find(0, 50)
query.close()

// Exact contact lookup via keyed blind index
val emailBlindIndex = Sealing.index("email", "ada@example.com")
val contact = contactBox.query(Contact_.emailIndex.equal(emailBlindIndex))
    .build()
    .findFirst()

// Free-text and substring search across contacts (in-memory over decrypted rows)
// Exposes a reactive StateFlow updated on address book changes:
val searchResults: StateFlow<List<Contact>>? = client.contacts.search("ali")

Always close() a query you built, or use query.use { }.