docs.sheetjs.com/docz/docs/03-demos/41-nosql.md
2022-08-26 01:39:17 -04:00

4.5 KiB

title
NoSQL Data Stores

import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

So-called "Schema-less" databases allow for arbitrary keys and values within the entries in the database. K/V stores and Objects add additional restrictions.

:::note

These data stores are capable of storing structured data. Those use cases are covered in the Database demo.

:::

Arbitrary Data to Spreadsheets

There is no natural way to translate arbitrarily shaped schemas to worksheets in a workbook. One common trick is to dedicate one worksheet to holding named keys. For example, considering the JS object:

{
  "title": "SheetDB",
  "metadata": {
    "author": "SheetJS",
    "code": 7262
  },
  "data": [
    { "Name": "Barack Obama", "Index": 44 },
    { "Name": "Donald Trump", "Index": 45 },
  ]
}

A dedicated worksheet should store the one-off named values:

XXX|        A        |    B    |
---+-----------------+---------+
 1 | Path            | Value   |
 2 | title           | SheetDB |
 3 | metadata.author | SheetJS |
 4 | metadata.code   |    7262 |

Data Stores

Redis

Redis has 5 core data types: "String", List", "Set", "Sorted Set", and "Hash". Since the keys and values are limited to simple strings (and numbers), it is possible to store complete databases in a single worksheet.

SheetJSRedis.xlsx

Mapping

The first row holds the data type and the second row holds the property name.

Strings can be stored in a unified String table. The first column holds keys and the second column holds values:

XXX|    A    |   B   |
---+---------+-------+
 1 | Strings |       |
 2 |         |       |
 3 | Hello   | World |
 4 | Sheet   | JS    |

The SheetJS array-of-arrays representation of the string table is an array of key/value pairs:

let aoa = ["Strings"]; aoa.length = 2; // [ "Strings", empty ]
const keys = await client.KEYS("*");
for(let key of keys) {
  const type = await client.TYPE(key);
  if(type == "string") aoa.push([key, await client.GET(key)]);
}

Lists are unidimensional and can be stored in their own columns.

XXX|    C    |
---+---------+
 1 | List    |
 2 | List1   |
 3 | List1V1 |
 4 | List1V2 |

The SheetJS array-of-arrays representation of lists is a column of values.

if(type == "list") {
  let values = await client.LRANGE(key, 0, -1);
  aoa = [ ["List"], [key] ].concat(values.map(v => [v]));
}

Sets are unidimensional and can be stored in their own columns.

XXX|   D   |
---+-------+
 1 | Set   |
 2 | Set1  |
 3 | Set1A |
 4 | Set1B |

The SheetJS array-of-arrays representation of sets is a column of values.

if(type == "set") {
  let values = await client.SMEMBERS(key);
  aoa = [ ["Set"], [key] ].concat(values.map(v => [v]));
}

Sorted Sets have an associated score which can be stored in the second column.

XXX|    E    | F |
---+---------+---+
 1 | Sorted  |   |
 2 | ZSet1   |   |
 3 | Key1    | 1 |
 4 | Key2    | 2 |

The SheetJS array-of-arrays representation is an array of key/score pairs.

if(type == "zset") {
  let values = await client.ZRANGE_WITHSCORES(key, 0, -1);
  aoa = [ ["Sorted"], [key] ].concat(values.map(v => [v.value, v.score]));
}

Hashes are stored like the string table, with key and value columns in order.

XXX|   G   |   H   |
---+-------+-------+
 1 | Hash  |       |
 2 | Hash1 |       |
 3 | Key1  | Val1  |
 4 | Key2  | Val2  |

The SheetJS array-of-arrays representation is an array of key/value pairs.

if(type == "hash") {
  let values = await client.HGETALL(key);
  aoa = [ ["Hash"], [key] ].concat(Object.entries(values));
}

Example

Complete Example (click to show)
  1. Set up and start a local Redis server

  2. Download the following scripts:

  1. Install dependencies and run:
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz redis
node SheetJSRedisTest.mjs

Inspect the output and compare with the data in SheetJSRedisTest.mjs.

Open SheetJSRedis.xlsx and verify the columns have the correct data