How to search JSON data in MySQL?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
MySQL can store JSON natively, which is useful when part of your data is nested or varies from row to row. Searching that JSON efficiently requires knowing the difference between extracting a value, checking whether a path contains something, and indexing frequently queried attributes.
Querying JSON by Path
Suppose you store order metadata in a JSON column.
To filter by a scalar field, extract the value at a JSON path.
The ->> operator returns an unquoted text value, which is convenient for comparisons. The -> operator returns JSON. That difference matters because comparing JSON and comparing strings are not the same thing.
Searching Arrays and Nested Values
For arrays or nested objects, JSON_CONTAINS and JSON_SEARCH are often the right tools.
That query finds rows where the tags array contains vip.
If you need to search for a text value anywhere under a path, use JSON_SEARCH.
JSON_SEARCH returns the matching path when it finds one, so checking for IS NOT NULL is the usual pattern in a WHERE clause.
Making Searches Faster
JSON queries can be flexible, but they are not free. If you frequently filter on the same JSON property, create a generated column and index that column.
After that, the query becomes simpler and more index-friendly:
This is a practical pattern when JSON is convenient for storage but some fields behave like normal relational columns in your query workload.
When JSON Fits and When It Does Not
JSON works well for optional metadata, nested payloads, or data coming from external APIs. It is less ideal when the same property is queried constantly, joined across tables, or constrained by relational rules. In those cases, a standard column is often the better design.
A good rule is to keep the flexible part flexible and promote hot fields into indexed columns once the access pattern becomes clear.
Common Pitfalls
The most common mistake is forgetting that JSON_EXTRACT returns JSON. If you compare the result directly to a plain SQL string, the match may fail because of quoting. Use ->>, JSON_UNQUOTE, or a generated column when you need text semantics.
Another mistake is expecting MySQL to optimize arbitrary JSON expressions automatically. Without generated columns or functional indexes, many JSON filters become full table scans.
Be careful with path spelling and array positions. JSON paths are case-sensitive with respect to the keys stored in the document, and one wrong path silently produces NULL, which can make debugging slow.
Finally, do not turn an entire relational schema into one JSON blob just because MySQL allows it. JSON is a tool for specific flexibility needs, not a replacement for thoughtful schema design.
Summary
- Use
->>orJSON_UNQUOTE(JSON_EXTRACT(...))when you need text values from JSON. - Use
JSON_CONTAINSfor membership checks andJSON_SEARCHfor path-based text lookup. - Add generated columns and indexes for frequently queried JSON attributes.
- Expect poor performance if you search JSON heavily without indexing strategy.
- Keep JSON for flexible data, and move hot fields into normal columns when needed.

