This is similar to how logic in JS is implemented. Executing similar code on restored database could work too, but it would be really bad in terms of performance (read all messages into JS, create search ops, process each search op separately), and I want to avoid slowing and adding additional steps to restore (on JS side).
This is solved fully using SQLite, where together with copying content, we fill the search index (it is not possible to copy virtual tables).
We use JSON_EXTRACT, which is used elsewhere in the codebase, and it is implemented in a safe way so malformed content field should not break restore.