SQL Databases ​
Nostrify can store events in Postgres, SQLite, and more thanks to Kysely.
The NDatabase
class accepts a Kysely instance and then executes queries on it. First create a Kysely instance and connect it to whichever database you choose, then pass it to NDatabase.
const kysely = new Kysely(/* set up your database */);
const db = new NDatabase(kysely);
await db.migrate();
Usage ​
NDatabase implements NStore
, allowing you to use it interchangeably with relays.
Insert an event ​
await db.event(event);
Query events ​
const events = await db.query([{ kinds: [1, 6], limit: 5 }]);
Count events ​
const { count } = await db.count([{ kinds: [1, 6] }]);
Remove events ​
await db.remove([{ kinds: [1, 6] }]);
Full text search ​
NDatabase supports NIP-50 search with the fts
option:
const db = new NDatabase(kysely, {
fts: 'postgres', // can be 'postgres' or 'sqlite'
});
postgres
uses the built-in Postgres FTS.sqlite
uses the built-in SQLite FTS5.
Search filters ​
Once enabled, you can query with search
filters:
const events = await db.query([{ kinds: [1], search: 'hello world' }]);
NOTE
If FTS is not enabled, the search
filter will always return an empty array.
Tables ​
NDatabase manages two tables:
nostr_events
stores Nostr events. Each property has its own column.nostr_tags
stores tags to be indexed for tag filters.
TIP
By default, all single-letter tags are indexed. You can customize this behavior by passing a custom indexTags
function into NDatabase.
NOTE
If FTS is enabled, one of the following tables will also be created:
nostr_pgfts
to store the Postgres search index.nostr_fts5
to store the SQLite search index.
Migrating the database ​
Run await db.migrate()
to create the necessary tables and indexes before use. You should call this every time the program starts.
SQLite on Deno ​
Using @db/sqlite
and @soapbox/kysely-deno-sqlite
, you can connect to an SQLite database in Deno.
import { Database } from '@db/sqlite';
import { DenoSqlite3Dialect } from '@soapbox/kysely-deno-sqlite';
import { Kysely } from 'kysely';
const kysely = new Kysely({
dialect: new DenoSqlite3Dialect({
database: new Database('./nostr.sqlite3'),
}),
});
const db = new NDatabase(kysely);
await db.migrate();
Postgres on Deno ​
Using x/kysely_deno_postgres you can connect to a Postgres database in Deno.
import { NDatabase } from '@nostrify/nostrify';
import { PostgreSQLDriver } from 'https://deno.land/x/[email protected]/mod.ts';
import { Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from 'kysely';
const kysely = new Kysely({
dialect: {
createAdapter() {
return new PostgresAdapter();
},
// @ts-ignore mismatched kysely versions probably
createDriver() {
return new PostgreSQLDriver({
database: 'test',
hostname: 'localhost',
user: 'postgres',
password: 'postgres',
port: 5432,
});
},
createIntrospector(db: Kysely<unknown>) {
return new PostgresIntrospector(db);
},
createQueryCompiler() {
return new PostgresQueryCompiler();
},
},
});
const db = new NDatabase(kysely);
await db.migrate();
TIP
There are a few different Postgres drivers for Deno. See which one works best for you.
Other databases ​
Kysely maintains a list of supported dialects.
It may be possible to get other dialects working. Or build your own!