TairDoc is a document data structure similar to RedisJSON. Use it to store, query, and manipulate JSON documents with full CRUD support.
Key features:
Full JSON standard support
JSONPath support (RFC draft-4) via
JSON.GET; specific selectors including dot wildcard, index, and filter selectors require version 1.8.4 or laterComplete JSON Pointer syntax support (RFC 6901)
Binary tree storage for efficient child element retrieval
JSON-to-XML and JSON-to-YAML conversion via
JSON.GET
Release notes:
TairDoc was released with Tair memory-optimized instances. It supports complete JSONPointer syntax and partial JSONPath syntax (only
JSON.GETsupports the JSONPath syntax).On May 17, 2022, TairDoc V1.8.4 was released with full JSONPath support for
JSON.GET, including the dot wildcard selector, index selector, and filter selector. We recommend updating your instance's minor version to 1.8.4 or later.
Prerequisites
Before you begin, make sure you have:
A Tair DRAM-based instance
Instance minor version 1.8.4 or later (required for full JSONPath support via
JSON.GET)
To update your instance to the latest minor version, see Update the minor version of an instance.
For cluster or read/write splitting instances, update proxy nodes to the latest minor version to make sure all commands work as expected.
Command list
| Command | Description | Time complexity |
|---|---|---|
| JSON.SET | Create a TairDoc key or update a JSON element at a path | O(N) |
| JSON.GET | Retrieve a JSON element from a path | O(N) |
| JSON.DEL | Delete a JSON element or key | O(N) |
| JSON.TYPE | Get the type of a JSON element | O(N) |
| JSON.MERGE | Merge a JSON value into a path | O(N) |
| JSON.NUMINCRBY | Increment a numeric JSON element | O(N) |
| JSON.STRAPPEND | Append a string to a JSON string element | O(N) |
| JSON.STRLEN | Get the length of a JSON string element | O(N) |
| JSON.ARRAPPEND | Append elements to the end of an array | O(M×N) |
| JSON.ARRPOP | Remove and return an element from an array | O(M×N) |
| JSON.ARRINSERT | Insert elements before a given index in an array | O(M×N) |
| JSON.ARRLEN | Get the length of an array | O(N) |
| JSON.ARRTRIM | Trim an array to a specified range | O(N) |
| DEL | Delete one or more TairDoc keys (native Redis command) | — |
Syntax conventions used in this reference:
UPPERCASE: command keyword_italic_: variable[option]: optional parameterA | B: mutually exclusive options...: parameter can be repeated
JSON.SET
Syntax: JSON.SET key path json [NX | XX]
Creates a TairDoc key and stores a JSON element at the specified path. If the key and path already exist, updates the element.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path within the key. Use . or $ for the root |
json | The JSON element to store |
NX | Write only if the path does not exist |
XX | Write only if the path already exists |
Return values:
| Result | Return value |
|---|---|
| Success | OK |
XX specified but path does not exist | nil |
NX specified but path already exists | nil |
| Invalid path | ERR could not find object to add, please check path |
Example — create a JSON document:
The following command creates a doc key at the root path ($) and stores a bookstore document with four books and a bicycle:
JSON.SET doc $ '{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }'Expected output:
OKJSON.GET
Syntax: JSON.GET key path [FORMAT XML | YAML] [ROOTNAME root] [ARRNAME arr]
Retrieves the JSON element at the specified path. Supports both JSONPath and JSON Pointer syntax.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path within the key. Accepts JSONPath ($-style) and JSON Pointer (.-style) syntax |
FORMAT | Output format: XML or YAML. If omitted, returns JSON |
ROOTNAME | Tag name for the root element in XML output. Valid only when FORMAT XML is set |
ARRNAME | Tag name for array elements in XML output. Valid only when FORMAT XML is set |
Return values:
| Result | Return value |
|---|---|
| Success | The JSON element at the specified path |
| Error | Error message |
Example — retrieve a document as XML:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : 42}'Then retrieve it as XML, specifying ROOT as the root tag name and ARR as the array tag name:
JSON.GET doc . FORMAT XML ROOTNAME ROOT ARRNAME ARRExpected output:
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><ROOT><foo>bar</foo><baz>42</baz></ROOT>"JSON.DEL
Syntax: JSON.DEL key path
Deletes the JSON element at the specified path. If no path is given, deletes the entire key. Silently does nothing if the key or path does not exist.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the element to delete. If omitted, the entire key is deleted |
Return values:
| Result | Return value |
|---|---|
| Success | 1 |
| Key or path not found | 0 |
Example — delete a field:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : 42}'Delete the foo field:
JSON.DEL doc .fooExpected output — 1 indicates the element was deleted:
(integer) 1JSON.TYPE
Syntax: JSON.TYPE key path
Returns the type of the JSON element at the specified path.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the element |
Return values:
| Result | Return value |
|---|---|
| Success | One of: boolean, string, number, array, object, raw, reference, const, null |
| Failure | 0 |
| Key or path not found | nil |
Example — get the type of a field:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : 42}'Get the type of the foo field ("bar" is a string):
JSON.TYPE doc .fooExpected output:
stringJSON.MERGE
Syntax: JSON.MERGE key path value
Merges a JSON value into the specified path. Supports adding new values, updating existing values, and deleting values at the specified path.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path to merge into. Supports partial JSONPath syntax (e.g., $.a.b.c, $.a['b']). Does not support recursive descent ($..) or wildcard ($*) expressions |
value | The JSON value to merge. Compatible with JSON Merge Patch (RFC 7386) |
Return values:
| Result | Return value |
|---|---|
| Success | OK |
| Invalid value | Error (parsing the merge patch failed) |
Example — add, update, and delete values in one operation:
First, create the document:
JSON.SET doc $ '{"f1": {"a":1}, "f2":{"a":2}}'Merge changes: set f1 to null (deletes it), update f2.a and add f2.b, and add a new f3 array:
JSON.MERGE doc $ '{"f1": null, "f2":{"a":3, "b":4}, "f3":[2,4,6]}'Expected output:
OKVerify the result with JSON.GET doc .. The f1 key is removed because setting a field to null in a merge patch deletes it:
"{\"f2\":{\"a\":3,\"b\":4},\"f3\":[2,4,6]}"JSON.NUMINCRBY
Syntax: JSON.NUMINCRBY key path value
Increments the numeric JSON element at the specified path. Both the existing element and the increment value must be of the same type — either integer or double.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the numeric element |
value | The amount to add |
Return values:
| Result | Return value |
|---|---|
| Success | The new value after increment |
| Key or path not found | Error |
Example — increment a numeric field:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : 42}'Increment baz by 10 (42 + 10 = 52):
JSON.NUMINCRBY doc .baz 10Expected output:
"52"JSON.STRAPPEND
Syntax: JSON.STRAPPEND key path json-string
Appends a string to the JSON string element at the specified path. Both the existing element and the appended value must be of the string type.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the string element |
json-string | The string to append |
Return values:
| Result | Return value |
|---|---|
| Success | The new length of the string |
| Key not found | -1 |
Example — append to a string field:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : 42}'Append rrrrr to foo — "bar" becomes "barrrrrr", which has 8 characters:
JSON.STRAPPEND doc .foo rrrrrExpected output:
(integer) 8JSON.STRLEN
Syntax: JSON.STRLEN key path
Returns the character length of the JSON string element at the specified path. The element must be of the string type.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the string element |
Return values:
| Result | Return value |
|---|---|
| Success | Length of the string |
| Key not found | -1 |
Example — get the length of a string field:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : 42}'Get the length of foo — "bar" has 3 characters:
JSON.STRLEN doc .fooExpected output:
(integer) 3JSON.ARRAPPEND
Syntax: JSON.ARRAPPEND key path json [json ...]
Appends one or more JSON elements to the end of an array. Time complexity is O(M×N), where M is the number of elements to append and N is the current array length.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the array |
json | One or more JSON elements to append |
Return values:
| Result | Return value |
|---|---|
| Success | The new length of the array |
| Key not found | -1 |
Example — append multiple elements to an array:
First, create the document:
JSON.SET doc . '{"id": [1,2,3]}'Append null, false, and true to the id array. The array grows from 3 to 6 elements:
JSON.ARRAPPEND doc .id null false trueExpected output:
(integer) 6JSON.ARRPOP
Syntax: JSON.ARRPOP key path [index]
Removes and returns the element at the specified index in an array. Time complexity is O(M×N), where M is the number of child elements in the key and N is the array length.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the array |
index | Index of the element to remove. Starts from 0; negative values count from the end. Defaults to the last element if omitted |
Return values:
| Result | Return value |
|---|---|
| Success | The removed element |
| Array is empty | ERR array index outflow |
Example — remove the first element of an array:
First, create the document:
JSON.SET doc . '{"id": [1,2,3]}'Remove and return the element at index 0 (the first element, 1):
JSON.ARRPOP doc .id 0Expected output:
"1"JSON.ARRINSERT
Syntax: JSON.ARRINSERT key path [index] json [json ...]
Inserts one or more JSON elements into an array before the specified index. Time complexity is O(M×N), where M is the number of elements to insert and N is the current array length.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the array |
index | Position before which to insert. Starts from 0; negative values count from the end. Defaults to the last position if omitted |
json | One or more JSON elements to insert |
Return values:
| Result | Return value |
|---|---|
| Success | The new length of the array |
| Array is empty | ERR array index outflow |
Example — insert elements at the beginning of an array:
First, create the document:
JSON.SET doc . '{"id": [1,2,3]}'Insert 10 and 15 before index 0. The resulting array is [10, 15, 1, 2, 3]:
JSON.ARRINSERT doc .id 0 10 15Expected output:
(integer) 5JSON.ARRLEN
Syntax: JSON.ARRLEN key path
Returns the number of elements in an array.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the array |
Return values:
| Result | Return value |
|---|---|
| Success | Length of the array |
| Key not found | -1 |
Example — get the length of an array:
First, create the document:
JSON.SET doc . '{"id": [1,2,3]}'Get the number of elements in the id array:
JSON.ARRLEN doc .idExpected output:
(integer) 3JSON.ARRTRIM
Syntax: JSON.ARRTRIM key path start stop
Trims an array so that only elements within the [start, stop] range (inclusive) remain. All elements outside this range are removed.
Parameters:
| Parameter | Description |
|---|---|
key | The TairDoc key |
path | Path of the array |
start | Start index (0-based, inclusive) |
stop | End index (0-based, inclusive) |
Return values:
| Result | Return value |
|---|---|
| Success | Length of the array after trimming |
| Key not found | -1 |
Example — trim an array to a subrange:
First, create the document:
JSON.SET doc . '{"id": [1,2,3,4,5,6]}'Trim the array to keep only elements at index 3 and 4 (values 4 and 5). Elements outside this range are discarded:
JSON.ARRTRIM doc .id 3 4Expected output — 2 elements remain:
(integer) 2JSONPath
JSON.GET supports the JSONPath RFC draft-4 syntax for flexible queries. Full JSONPath support requires version 1.8.4 or later.
Supported selectors:
| Selector | Description | ||
|---|---|---|---|
$ | Root element | ||
@ | Current element | ||
.name | Child element | ||
.. | Descendant elements | ||
* | Wildcard — all child or array elements | ||
[ ] | Array index (0-based); supports lists ([0,1]) and element names (['name']) | ||
[start:end:step] | Array slice selector | ||
?... | Filter selector | ||
() | Expression; operator priority: `( ) > && > | ` |
Query examples:
The following examples use this bookstore document. Create it first:
JSON.SET dockey $
'{
"store": {
"book": [{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}'Expected output:
OKRoot selector
Query the entire JSON object:
JSON.GET dockey $Expected output:
"[{"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}}}]"Dot selector
Query all fields of the bicycle:
JSON.GET dockey $.store.bicycle.*Expected output:
"["red",19.95]"Query the bicycle price:
JSON.GET dockey $.store.bicycle.priceExpected output:
"[19.95]"Index selector
Query all fields of the first book:
JSON.GET dockey $.store.book[0]Expected output:
"[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}]"Query the titles of all books:
JSON.GET dockey "$.store.book[*]['title']"Expected output:
"["Sayings of the Century","Sword of Honour","Moby Dick","The Lord of the Rings"]"Array slice selector
Query the first three books using a slice with step 1:
JSON.GET dockey $.store.book[0:2:1]Expected output:
"[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]"Descendant selector
Query all prices in the store (both books and bicycle):
JSON.GET dockey $..priceExpected output:
"[8.95,12.99,8.99,22.99,19.95]"List selector
Query the first and third books:
JSON.GET dockey $.store.book[0,2]Expected output:
"[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]"Filter selector
Query books that have an isbn field:
JSON.GET dockey $.store.book[?(@.isbn)]Expected output:
"[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]"Query books priced under 10:
JSON.GET dockey '$.store.book[?(@.price < 10)]'Expected output:
"[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]"Query books priced at 12.99, priced above 19.95, or in the reference category (combined expression):
JSON.GET dockey "$..book[?((@.price == 12.99 || @.price > $.store.bicycle.price) || @.category == 'reference')]"Expected output:
"[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]"JSON Pointer
TairDoc fully supports the JSON Pointer syntax (RFC 6901). Use /-delimited paths to navigate into a document.
Example — retrieve a nested array element:
First, create the document:
JSON.SET doc . '{"foo": "bar", "baz" : [1,2,3]}'Retrieve the first element of the baz array using JSON Pointer path /baz/0:
JSON.GET doc /baz/0Expected output:
"1"