level-path-index
index properties of items that live in a tree of materialized paths - using levelup
installation
$ npm install level-path-index
what it does
Indexes key=value properties of an object against a materialised path so you can ask things like:
- match all items that match 'color=red' and are descendents of /home/rodney
- match all items that are direct children of /home/rodney
example
var level = ;var sub = ;var pathindex = ; var db = var treedb = db var treeindex =
Then stick some data in your leveldb:
treeindex
Now we can search for things that match color=red and live somewhere under '/home/rodney':
var through = ; treeindex /*{ name:'goofy 1', colors:['red', 'blue'], ...}{ name:'cat yum yums', colors:['red', 'yellow'], ...} */
You can also find direct children of an entry and use multiple clauses to your query:
treeindex /*{ name:'goofy 1', colors:['red', 'blue'], ...}*/
index structure
In a single query step - there are 3 parts in the combined index:
- fieldname
- value
- tree location
Assuming this question:
find all descendents of '/a' where the color is red
Then we have:
- fieldname (color)
- value (red)
- tree location (/a/b/c)
If we create the index in this strict order then the key would become:
color~red~/a/b/c
descendent query
The first part of the query is ok - color=red - this would mean leveldb range like this:
start:'dv~color~red~' end:'dv~color~red~\xff'
Because we are doing a (d)escendent query with some (v)alues - the key is prepended with 'dv'
Now to include the path - we are looking below '/a' - we add the splitter '/' on the end and the level range becomes:
{
start:'dv~color~red~/a/',
end:'dv~color~red~/a/\xff'
}
This would match our item - which is living 2 layers below (in '/a/b/c')
child query
Children is slightly different - to make child request fast an extra index is created.
This avoids loading all descendents of a top level node when all you want are its children.
The child index works by seperating the parent path from the node path.
For our example (color~red~/a/b/c) the following index would also be created:
cv~color~red~/a/b/~_~c
The child value indexes are prepended with 'cv'.
The split between the parent and child path means we can ask for children of '/a/b' and only the direct children are loaded.
{
start:'cv~color~red~/a/b/~_~',
end:'cv~color~red~/a/b/~_~\xff'
}
This would match '/a/b/c' (cv~color~red~/a/b/~_~c) as a direct child
Empty queries
You can also load descendents and children with a blank query - a seperate index for empty queries is used - the key for our example is simply:
/a/b/c
So if we just wanted descendents of '/a/b' we can use this range:
start:'dt~/a/b/' end:'dt~/a/b/\xff'
The empty query indexes (t)ree for descendents are prepended with 'dt' and for children 'ct'
api
pathindex(db, [indexdb], mapper(key, value, emit))
Pass the document database, optionally the name/sublevel for the indexes and a mapper function that will index each document as it is updated
the mapper is run with the key and value of the update and an emit function.
emit is a function with a (path, field, value) signature and be called multiple times to add an index to the document.
var tree =
index.save(key, value, callback)
Insert a value for a key and create the indexes based on your mapper function.
tree
index.batch(arr, callback)
Insert an array of documents - this must be a list of leveldb batch commands e.g.:
tree
index.descendentStream(path, searchTerms)
Return a read stream for entries that live at or below the given path:
tree // /uk/north/east/newcastle// /uk/north/west/liverpool
You can use multiple search terms and the values can be lists which all must match:
tree
index.childStream(path, searchTerms)
This is the same as descendent stream but for entries directly below the given path:
tree // /uk/south/west/bristol
index.descendentKeyStream(path, searchTerms)
This is the same as descendent stream but will return only the keys of the matched items
tree // /uk/south/west/bristol// /uk/south/east/london
index.childKeyStream(path, searchTerms)
This is the same as child stream but will return only the keys of the matched items
tree // /uk/south/west/bristol
pull streams
Each of the 4 read stream methods also come with pull-stream equivalents
index.descendentPullStream(path, searchTerms)
index.descendentKeyPullStream(path, searchTerms)
index.childPullStream(path, searchTerms)
index.childKeyPullStream(path, searchTerms)
license
MIT