Tilia - local json database for deno
With Tilia you can store and query JSON objects in local files with Deno. Like in mongoDB we call such objects βdocumentsβ. Those documents are stored in collections. A collection is simply a file where every line is one document - meaning a JSON object you stored.
Unless other libs around we do not load the complete collection file into memory. Instead we use file streams to only store a portion of the file in memory at the same time and therefore consume less resources (RAM).
Tilia is a fork and rewrite of DnDB.
Not yet:
- indexes for faster queries
- count, limit
- line position index to fetch data without looping
- splitting of large files
Usage
Tilia works by instantiating collections stored in a file given by the user in the instance constructor. By default the created instance exposes the necessary methods to work the collection.
All the api methods are asynchronous by default, so they return promises.
Collection
import Collection from 'https://deno.land/x/tilia/src/collection.ts';
const collection = new Collection({ filename: './collection.json.db', autoload: true });
When you instantiate a collection you can pass it a config object with a couple of options:
filename
: The filename is the absolute path to your target file. If no
filename is provided, DnDB will automatically create one in the current
working directory, and if a full path is not specified, it will resolve the
file name within the CWD.
autoload
: The autoload option runs the loadDatabase
method which creates
the persistent file the first time DnDB is running in your project, this is
optional, but if the loadDatabase method is not executed, the instance will
not work until the persistent file exists.
bufSize
: The bufSize parameter rewrites the default size of the buffer. It
must be indicated in numbers and represents the amount of bytes to be
allocated. By default 4096 bytes.
Insert
All data types are allowed, but field names starting with '$' are reserved for data querying.
If the document does not already contain an _id
field, it will be automatically generated. The _id
of a document, once set, shouldn't be modified.
const obj = {
name: 'Denyn',
lastName: 'Crawford',
};
const inserted = await collection.insert(obj);
Paramaters
data: Object | Array<Object>
JSON object or array of objects
const foo = 'foo';
const inserted = await collection.insert([{ name: 'denyn' }, { name: foo }]);
Return
Array/object with the inserted object or array of objects.
Find
There are two methods to query the database:
find
: Finds all the documents that match the query and returns an array of matching documents.
findOne
: Finds the first document that matches the query and returns exact first matching object.
You can select documents based on field equality or use comparison operators
($lt
, $lte
, $gt
, $gte
, $in
, $nin
, $neq
). You can also use logical
operators $or
, $and
, $not
and $eq
.
π List of rules and operators
You can use regular expressions in two ways: in basic querying in place of a string, or with the $regex operator.
const docs = await collection.find({ name: 'Denyn' });
Finding unique document:
const doc = await collection.findOne({ username: 'denyncrawford' });
Deep querying syntax:
const docs = await collection.find({ fullName: { lastName: 'Crawford' } });
You can also use dot notation to find documents by deep querying.
let docs = await collection.find({ 'fullName.lastName': 'Crawford' });
Using dot notation to find inside arrays:
let docs = await collection.find({ 'list.games.0': 'Doom' });
Projection
You can give find
and findOne
an optional second argument, projections. The
syntax is the same as MongoDB: { a: 1, b: 1 }
to return only the a and b
fields, { a: 0, b: 0 }
to omit these two fields. You cannot use both modes at
the time, except for _id which is by default always returned and which you can
choose to omit. You can project on nested documents. π List of rules and operators
const docs = await collection.find({ planet: 'Mars' }, { planet: 1, system: 1 });
// docs is [{ planet: 'Mars', system: 'solar', _id: '45fb71a3-531a-4285-88c6-45db802a0a95' }]
Update
There are two methods to update documents:
update
- returns array with the new updated collection
updateOne
- returns object with the new updated document
Parameters
The first argument follows the same query rules as find
and findOne
. The second agument modifies the matching field values by following aggregation operators. π List of rules and operators.
const updated = await collection.update(
{ name: 'denyn' },
{
$set: { pet: 'Boots' },
}
);
Remove
To delete documents DnDB exposes the method:
remove
- returns array with the new removed collection
removeOne
- returns object with the new removed document
The remove method follows the same query rules as in find
and findOne
at
first argument, it will remove all the documents that matches the query.
const removed = await collection.remove({ _id: 'id2' });
Notice: If you dont want to delete but just unset one property of a document you need to use update with the $unset operator. π List of rules and operators.