adding skills and site

This commit is contained in:
2026-02-03 12:27:57 -08:00
parent ad37eda106
commit 2bc3b78be8
64 changed files with 20081 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
---
name: how-to-store-sqlite-as-nosql-store
description: Discover how to leverage SQLite's JSON support to build a NoSQL-like document store, complete with TTL-based expiration, within this powerful embedded database.
metadata:
url: https://rodydavis.com/posts/sqlite/no-sql
last_modified: Tue, 03 Feb 2026 20:04:37 GMT
---
# How to store SQLite as NoSQL Store
[SQLite](https://www.sqlite.org/) is a very capable edge database that can store various shapes of data.
[NoSQL databases](https://www.mongodb.com/nosql-explained#:~:text=Some%20say%20the%20term%20%E2%80%9CNoSQL,format%20other%20than%20relational%20tables.) are very popular due to the schema-less nature of storing of the data but it is totally possible to store these documents in SQLite.
SQLite actually has great [JSON support](https://www.sqlite.org/json1.html) and even supports [JSONB](https://sqlite.org/draft/jsonb.html).
## Create the table 
To store JSON documents we need to create a table to store the values as strings.
```
CREATE TABLE documents (
path TEXT NOT NULL PRIMARY KEY,
data TEXT,
ttl INTEGER,
created INTEGER NOT NULL,
updated INTEGER NOT NULL,
UNIQUE(path)
);
```
path
data
ttl
created
updated
/posts/1
{"id":1}
NULL
0
0
/posts/2
{"id":2}
NULL
0
0
/users/1
{"id":1}
NULL
0
0
The basic idea is to store a JSON object and an unique path.
There is an optional [TTL](https://www.cloudflare.com/learning/cdn/glossary/time-to-live-ttl/#:~:text=What%20is%20time%2Dto%2Dlive%20\(TTL\)%20in%20networking,CDN%20caching%20and%20DNS%20caching.) to automatically delete rows when they reach the stale date.
## Save a document 
To save a document we can encode our JSON as a string or binary and save in in the table with a unique path.
```
INSERT OR REPLACE
INTO documents (path, data, ttl, created, updated)
VALUES (:path, :data, :ttl, :created, :updated)
RETURNING *;
```
You can also use JSON functions to save the Object to a valid JSON string.
```
INSERT OR REPLACE
INTO documents (path, data, ttl, created, updated)
VALUES ("/posts/1", json('{"id" 1}'), NULL, 0, 0)
RETURNING *;
```
path
data
ttl
created
updated
/posts/1
{"id":1}
NULL
0
0
## Reading a document 
To read a document we just need the path. If a TTL is set we can [calculate if the current date](https://www.sqlite.org/lang_datefunc.html) is greater than the offset and not return the document.
```
SELECT * FROM documents
WHERE path = :path
AND (
(ttl IS NOT NULL AND ttl + updated < unixepoch())
OR
ttl IS NULL
);
```
path
data
ttl
created
updated
/posts/1
{"id":1}
NULL
0
0
## Get documents for a collection 
We can query all the docs for a given collection using some built-in functions and a path prefix:
```
SELECT *
FROM documents
WHERE (
path LIKE :prefix
AND
(LENGTH(path) - LENGTH(REPLACE(path, '/', ''))) = (LENGTH(:prefix) - LENGTH(REPLACE(:prefix, '/', '')))
)
AND (
(ttl IS NOT NULL AND ttl + updated < unixepoch())
OR
ttl IS NULL
)
ORDER BY created;
```
It is expected to search for a :prefix with the `/%` at the end:
`"/my/path/%" // search for /my/path`
## Deleting expired documents 
Using the TTL field we can delete all expired documents:
```
DELETE FROM documents
WHERE ttl IS NOT NULL
AND ttl + updated < unixepoch();
```
## Demo