|
| 1 | +--- |
| 2 | +title: JSON Queries |
| 3 | +description: How to query JSON fields in workers-qb. |
| 4 | +--- |
| 5 | + |
| 6 | +# Querying JSON Fields |
| 7 | + |
| 8 | +`workers-qb` takes advantage of the powerful JSON querying capabilities of the underlying database engines, especially Cloudflare D1. This allows you to efficiently work with JSON data stored in your database. |
| 9 | + |
| 10 | +JSON data is typically stored in a `TEXT` column. You can then use a variety of functions to manipulate and query this data directly in your SQL queries. |
| 11 | + |
| 12 | +## Extracting Values |
| 13 | + |
| 14 | +You can extract values from a JSON object using `json_extract`, `->`, and `->>`. |
| 15 | + |
| 16 | +- `json_extract(json, path)`: Extracts a value from a JSON object at a given path. |
| 17 | +- `->`: Extracts a value as a JSON object. |
| 18 | +- `->>`: Extracts a value as a SQL type. |
| 19 | + |
| 20 | +```typescript |
| 21 | +// Example JSON object stored in a 'data' column: |
| 22 | +// { "name": "John Doe", "age": 30, "is_active": true, "tags": ["a", "b"] } |
| 23 | + |
| 24 | +// Using json_extract |
| 25 | +const user = await qb.fetchOne({ |
| 26 | + tableName: 'users', |
| 27 | + fields: ["json_extract(data, '$.name') as name"], |
| 28 | + where: { conditions: 'id = ?', params: 1 }, |
| 29 | +}).execute(); |
| 30 | +// user.results.name will be "John Doe" |
| 31 | + |
| 32 | +// Using ->> |
| 33 | +const user = await qb.fetchOne({ |
| 34 | + tableName: 'users', |
| 35 | + fields: ["data ->> '$.name' as name"], |
| 36 | + where: { conditions: 'id = ?', params: 1 }, |
| 37 | +}).execute(); |
| 38 | +// user.results.name will be "John Doe" |
| 39 | +``` |
| 40 | + |
| 41 | +## Array Operations |
| 42 | + |
| 43 | +### Get Array Length |
| 44 | + |
| 45 | +Use `json_array_length` to get the number of elements in a JSON array. |
| 46 | + |
| 47 | +```typescript |
| 48 | +// data column: { "tags": ["a", "b", "c"] } |
| 49 | + |
| 50 | +const tagCount = await qb.fetchOne({ |
| 51 | + tableName: 'posts', |
| 52 | + fields: ["json_array_length(data, '$.tags') as count"], |
| 53 | + where: { conditions: 'id = ?', params: 1 }, |
| 54 | +}).execute(); |
| 55 | +// tagCount.results.count will be 3 |
| 56 | +``` |
| 57 | + |
| 58 | +### Expand Arrays for `IN` Queries |
| 59 | + |
| 60 | +`json_each` can be used to expand a JSON array into a set of rows, which is useful for `IN` clauses. |
| 61 | + |
| 62 | +```typescript |
| 63 | +const userIds = [1, 2, 3]; |
| 64 | +const users = await qb.fetchAll({ |
| 65 | + tableName: 'users', |
| 66 | + where: { |
| 67 | + conditions: `id IN (SELECT value FROM json_each(?))`, |
| 68 | + params: [JSON.stringify(userIds)], |
| 69 | + }, |
| 70 | +}).execute(); |
| 71 | +``` |
| 72 | + |
| 73 | +## Modifying JSON Data |
| 74 | + |
| 75 | +### Insert, Replace, and Set |
| 76 | + |
| 77 | +- `json_insert(json, path, value)`: Inserts a value at a given path. Does not overwrite existing values. |
| 78 | +- `json_replace(json, path, value)`: Replaces an existing value at a given path. |
| 79 | +- `json_set(json, path, value)`: Sets a value at a given path, overwriting if it exists or creating if it does not. |
| 80 | + |
| 81 | +```typescript |
| 82 | +import { Raw } from 'workers-qb'; |
| 83 | + |
| 84 | +// data column: { "name": "John Doe" } |
| 85 | + |
| 86 | +// Using json_set to add an age |
| 87 | +// We wrap the SQL function in `new Raw()` to tell the query builder to treat it as a raw expression. |
| 88 | +await qb.update({ |
| 89 | + tableName: 'users', |
| 90 | + data: { |
| 91 | + data: new Raw(`json_set(data, '$.age', 30)`), |
| 92 | + }, |
| 93 | + where: { conditions: 'id = ?', params: 1 }, |
| 94 | +}).execute(); |
| 95 | +// data column is now: { "name": "John Doe", "age": 30 } |
| 96 | +``` |
| 97 | + |
| 98 | +## Creating JSON |
| 99 | + |
| 100 | +You can create JSON objects and arrays directly in your queries. |
| 101 | + |
| 102 | +- `json_object(label1, value1, ...)`: Creates a JSON object from key-value pairs. |
| 103 | +- `json_array(value1, value2, ...)`: Creates a JSON array. |
| 104 | + |
| 105 | +```typescript |
| 106 | +const result = await qb.fetchOne({ |
| 107 | + tableName: 'users', // This can be any table |
| 108 | + fields: ["json_object('name', 'John', 'age', 30) as json_data"], |
| 109 | +}).execute(); |
| 110 | +// result.results.json_data will be { "name": "John", "age": 30 } |
| 111 | +``` |
| 112 | + |
| 113 | +## Other Useful Functions |
| 114 | + |
| 115 | +- `json_type(json, path)`: Returns the type of a JSON value. |
| 116 | +- `json_valid(json)`: Checks if a string is valid JSON. |
| 117 | +- `json_quote(value)`: Converts a SQL value to its JSON representation. |
| 118 | + |
| 119 | +```typescript |
| 120 | +// json_type |
| 121 | +const user = await qb.fetchOne({ |
| 122 | + tableName: 'users', |
| 123 | + fields: ["json_type(data, '$.age') as ageType"], |
| 124 | + where: { conditions: 'id = ?', params: 1 }, |
| 125 | +}).execute(); |
| 126 | +// user.results.ageType will be 'integer' |
| 127 | + |
| 128 | +// json_valid |
| 129 | +const result = await qb.fetchOne({ |
| 130 | + tableName: 'users', // This can be any table |
| 131 | + fields: ["json_valid('{\"a\":1}') as isValid"], |
| 132 | +}).execute(); |
| 133 | +// result.results.isValid will be 1 (true) |
| 134 | + |
| 135 | +// json_quote |
| 136 | +const result = await qb.fetchOne({ |
| 137 | + tableName: 'users', // This can be any table |
| 138 | + fields: ["json_quote('[1, 2, 3]') as json_string"], |
| 139 | +}).execute(); |
| 140 | +// result.results.json_string will be "[1,2,3]" |
| 141 | + |
| 142 | + |
0 commit comments