JSON & Full-Text Search
JSON & Full-Text Search
Section titled “JSON & Full-Text Search”MySQL supports JSON columns (store structured data) and FULLTEXT indexes (search text efficiently). Two powerful features for modern apps.
Real-World Analogy
Section titled “Real-World Analogy”Think of a shipping package:
- JSON column: Like a box where you can put anything — labels, fragile stickers, instructions. You don’t need a separate shelf for every possible item.
- FULLTEXT index: Like having an index at the back of a book. Instead of reading every page, you jump directly to pages containing “MongoDB”.
JSON Columns
Section titled “JSON Columns”-- Create a table with a JSON columnCREATE TABLE products ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), price DECIMAL(10,2), attributes JSON, -- flexible, store any extra fields created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- Insert JSON dataINSERT INTO products (name, price, attributes) VALUES ('Laptop Pro', 1499.99, '{ "color": "Space Gray", "ram": "16GB", "storage": "512GB SSD", "ports": ["USB-C", "HDMI"], "weight_kg": 1.8, "in_stock": true }'), ('Wireless Mouse', 49.99, '{ "color": "White", "connection": "Bluetooth 5.0", "battery_life": "12 months", "ergonomic": true }');Querying JSON Data
Section titled “Querying JSON Data”-- Access JSON fields with arrow operatorsSELECT name, attributes->>'$.color' AS color, attributes->>'$.ram' AS ramFROM productsWHERE attributes->>'$.color' = 'Space Gray';
-- JSON path expressionsSELECT * FROM productsWHERE JSON_EXTRACT(attributes, '$.storage') = '512GB SSD';
-- Check if a path existsSELECT * FROM productsWHERE JSON_CONTAINS_PATH(attributes, 'one', '$.ports');
-- Search within JSON arraysSELECT * FROM productsWHERE JSON_SEARCH(attributes, 'one', 'USB-C');
-- Check JSON typeSELECT JSON_TYPE('"hello"'); -- STRINGSELECT JSON_TYPE('123'); -- INTEGERSELECT JSON_TYPE('true'); -- BOOLEANModifying JSON Data
Section titled “Modifying JSON Data”-- Update a JSON fieldUPDATE productsSET attributes = JSON_SET(attributes, '$.color', 'Silver')WHERE id = 1;
-- Add a new JSON field (only if not exists)UPDATE productsSET attributes = JSON_INSERT(attributes, '$.warranty', '2 years')WHERE id = 1;
-- Remove a JSON fieldUPDATE productsSET attributes = JSON_REMOVE(attributes, '$.ports')WHERE id = 1;
-- Array operationsUPDATE productsSET attributes = JSON_ARRAY_APPEND(attributes, '$.ports', 'Thunderbolt 4')WHERE id = 1;When to Use JSON Columns
Section titled “When to Use JSON Columns”✅ Good use cases: - Storing flexible metadata / custom fields - Product attributes that vary by category - User preferences / settings - API response caching - Event logs / audit data
❌ Avoid when: - You need to query JSON fields frequently (use normal columns) - You need foreign key / referential integrity - You need indexes on JSON fields (it's possible but limited) - The data has a fixed schema (use regular columns)FULLTEXT Search
Section titled “FULLTEXT Search”-- Create a FULLTEXT indexCREATE TABLE articles ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title, body) -- combined text index);
-- Natural language search (default)SELECT * FROM articlesWHERE MATCH(title, body) AGAINST('database optimization');
-- Boolean mode (include/exclude terms)SELECT * FROM articlesWHERE MATCH(title, body) AGAINST('database -mysql' IN BOOLEAN MODE);-- Finds articles with "database" but NOT "mysql"
-- Search with wildcardSELECT * FROM articlesWHERE MATCH(title, body) AGAINST('optim*' IN BOOLEAN MODE);-- Matches: optimization, optimize, optimal...
-- Exact phraseSELECT * FROM articlesWHERE MATCH(title, body) AGAINST('"query optimization"' IN BOOLEAN MODE);FULLTEXT vs LIKE
Section titled “FULLTEXT vs LIKE”-- ❌ Slow: LIKE with leading wildcard (cannot use index)SELECT * FROM articles WHERE body LIKE '%optimization%';
-- ✅ Fast: FULLTEXT search (uses FULLTEXT index)SELECT * FROM articlesWHERE MATCH(body) AGAINST('optimization');
-- Comparison:-- LIKE '%word%' → Full table scan (scans every row)-- MATCH...AGAINST → Uses FULLTEXT index (fast)FULLTEXT Configuration
Section titled “FULLTEXT Configuration”-- Check minimum word length (default 3 for InnoDB)SHOW VARIABLES LIKE 'ft_min_word_len';
-- Check stop words (common words like "the", "and" that are ignored)SHOW VARIABLES LIKE 'ft_stopword_file';
-- Set minimum word length (in my.cnf)-- [mysqld]-- ft_min_word_len=2-- Then rebuild indexes:-- REPAIR TABLE articles QUICK;Hybrid Example: JSON + FULLTEXT
Section titled “Hybrid Example: JSON + FULLTEXT”-- Products with JSON attributes + full-text name searchSELECT name, price, attributes->>'$.color' AS colorFROM productsWHERE MATCH(name) AGAINST('laptop') AND attributes->>'$.ram' LIKE '%16GB%';In Simple Words
Section titled “In Simple Words”- JSON columns let you store flexible, schema-less data inside MySQL — great for varying attributes
- Use
->>to extract JSON values; useJSON_SET,JSON_REMOVEto modify - FULLTEXT indexes enable fast text search — much faster than
LIKE '%word%' MATCH...AGAINSTis the syntax for FULLTEXT queries- Use JSON for flexible data; use FULLTEXT for text-heavy searches