### find(cname, qobj, orarr, hints, cb)
Execute query on collection.
EJDB queries inspired by MongoDB (mongodb.org) and follows same philosophy.
Supported queries:
- Simple matching of String OR Number OR Array value:
- {'json.field.path' : 'val', ...}
- $not Negate operation.
- {'json.field.path' : {'$not' : val}} //Field not equal to val
- {'json.field.path' : {'$not' : {'$begin' : prefix}}} //Field not begins with val
- $begin String starts with prefix
- {'json.field.path' : {'$begin' : prefix}}
- $gt, $gte (>, >=) and $lt, $lte for number types:
- {'json.field.path' : {'$gt' : number}, ...}
- $bt Between for number types:
- {'json.field.path' : {'$bt' : [num1, num2]}}
- $in String OR Number OR Array val matches to value in specified array:
- {'json.field.path' : {'$in' : [val1, val2, val3]}}
- $nin - Not IN
- $strand String tokens OR String array val matches all tokens in specified array:
- {'json.field.path' : {'$strand' : [val1, val2, val3]}}
- $stror String tokens OR String array val matches any token in specified array:
- {'json.field.path' : {'$stror' : [val1, val2, val3]}}
- $exists Field existence matching:
- {'json.field.path' : {'$exists' : true|false}}
NOTE: Negate operations: $not and $nin not using indexes
so they can be slow in comparison to other matching operations.
NOTE: Only one index can be used in search query operation.
QUERY HINTS (specified by `hints` argument):
- $max Maximum number in the result set
- $skip Number of skipped results in the result set
- $orderby Sorting order of query fields.
Eg: ORDER BY field1 ASC, field2 DESC
hints: {
"$orderby" : {
"field1" : 1,
"field2" : -1
}
}
Many C API query examples can be found in `tcejdb/testejdb/t2.c` test case.
To traverse selected records cursor object is used:
- Cursor#next() Move cursor to the next record and returns true if next record exists.
- Cursor#hasNext() Returns true if cursor can be placed to the next record.
- Cursor#field(name) Retrieve value of the specified field of the current JSON object record.
- Cursor#object() Retrieve whole JSON object with all fields.
- Cursor#reset() Reset cursor to its initial state.
- Cursor#length Read-only property: Number of records placed into cursor.
- Cursor#pos Read/Write property: You can set cursor position: 0 <= pos < length
- Cursor#close() Closes cursor and free cursor resources. Cursor cant be used in closed state.
Call variations of find():
- find(cname, qobj, cb)
- find(cname, qobj, hints, cb)
- find(cname, qobj, qobjarr, cb)
- find(cname, qobj, qobjarr, hints, cb)
Arguments
- {String} cname Name of collection
- {Object} qobj Main JSON query object
- {Array}
[orarr]
Array of additional OR query objects (joined with OR predicate). - {Object}
[hints]
JSON object with query hints. - {Function} cb Callback args: (error, cursor, count)
cursor
: Cursor object to traverse records
count
: Total number of selected records
### findOne(cname, qobj, orarr, hints, cb)
Same as #find() but retrieves only one matching JSON object.
Call variations of findOne():
findOne(cname, qobj, cb)
findOne(cname, qobj, hints, cb)
findOne(cname, qobj, qobjarr, cb)
findOne(cname, qobj, qobjarr, hints, cb)
Arguments
- {String} cname Name of collection
- {Object} qobj Main JSON query object
- {Array}
[orarr]
Array of additional OR query objects (joined with OR predicate). - {Object}
[hints]
JSON object with query hints. - {Function} cb Callback args: (error, obj)
obj
Retrieved JSON object or NULL if it is not found.
### count(cname, qobj, orarr, hints, cb)
Convenient count(*) operation.
Call variations of count():
count(cname, qobj, cb)
count(cname, qobj, hints, cb)
count(cname, qobj, qobjarr, cb)
count(cname, qobj, qobjarr, hints, cb)
Arguments
- {String} cname Name of collection
- {Object} qobj Main JSON query object
- {Array}
[orarr]
Array of additional OR query objects (joined with OR predicate). - {Object}
[hints]
JSON object with query hints. - {Function} cb Callback args: (error, count)
count
: Number of matching records.
### dropStringIndex(cname, path, cb)
### dropNumberIndex(cname, path, cb)
### dropArrayIndex(cname, path, cb)
Drop index of String|Number|Array type for JSON field path
Arguments
- {String} cname Name of collection
- {String} path JSON field path
- {Function}
[cb]
Optional callback function. Callback args: (error)
EJDB C Library
One snippet intro
#include <tcejdb/ejdb.h>
static EJDB *jb;
int main() {
jb = ejdbnew();
if (!ejdbopen(jb, "addressbook", JBOWRITER | JBOCREAT | JBOTRUNC)) {
return 1;
}
EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
bson bsrec;
bson_oid_t oid;
bson_init(&bsrec);
bson_append_string(&bsrec, "name", "Bruce");
bson_append_string(&bsrec, "phone", "333-222-333");
bson_append_int(&bsrec, "age", 58);
bson_finish(&bsrec);
ejdbsavebson(coll, &bsrec, &oid);
fprintf(stderr, "\nSaved Bruce");
bson_destroy(&bsrec);
bson bq1;
bson_init_as_query(&bq1);
bson_append_start_object(&bq1, "name");
bson_append_string(&bq1, "$begin", "Bru");
bson_append_finish_object(&bq1);
bson_finish(&bq1);
EJQ *q1 = ejdbcreatequery(jb, &bq1, NULL, 0, NULL);
uint32_t count;
TCLIST *res = ejdbqrysearch(coll, q1, &count, 0, NULL);
fprintf(stderr, "\n\nRecords found: %d\n", count);
for (int i = 0; i < TCLISTNUM(res); ++i) {
void *bsdata = TCLISTVALPTR(res, i);
bson_print_raw(stderr, bsdata, 0);
}
fprintf(stderr, "\n");
tclistdel(res);
ejdbquerydel(q1);
bson_destroy(&bq1);
ejdbclose(jb);
ejdbdel(jb);
return 0;
}
Building & Installation
Prerequisites
System libraries:
On Debian/Ubuntu linux you can install it as follows:
sudo apt-get install gcc libcunit1 libcunit1-dev zlib1g zlib1g-dev
Building
cd ./tcejdb
./configure --disable-bzip --prefix=<installation prefix> && make && make check
make install
- library name: tcejdb (with pkgconfig)
- main include header:
<tcejdb/ejdb.h>
C API
EJDB API presented in ejdb.h C header file.
JSON processing API: bson.h
Queries
/**
* Create query object.
* Sucessfully created queries must be destroyed with ejdbquerydel().
*
* EJDB queries inspired by MongoDB (mongodb.org) and follows same philosophy.
*
* - Supported queries:
* - Simple matching of String OR Number OR Array value:
* - {'json.field.path' : 'val', ...}
* - $not Negate operation.
* - {'json.field.path' : {'$not' : val}} //Field not equal to val
* - {'json.field.path' : {'$not' : {'$begin' : prefix}}} //Field not begins with val
* - $begin String starts with prefix
* - {'json.field.path' : {'$begin' : prefix}}
* - $gt, $gte (>, >=) and $lt, $lte for number types:
* - {'json.field.path' : {'$gt' : number}, ...}
* - $bt Between for number types:
* - {'json.field.path' : {'$bt' : [num1, num2]}}
* - $in String OR Number OR Array val matches to value in specified array:
* - {'json.field.path' : {'$in' : [val1, val2, val3]}}
* - $nin - Not IN
* - $strand String tokens OR String array val matches all tokens in specified array:
* - {'json.field.path' : {'$strand' : [val1, val2, val3]}}
* - $stror String tokens OR String array val matches any token in specified array:
* - {'json.field.path' : {'$stror' : [val1, val2, val3]}}
* - $exists Field existence matching:
* - {'json.field.path' : {'$exists' : true|false}}
*
* NOTE: Negate operations: $not and $nin not using indexes
* so they can be slow in comparison to other matching operations.
*
* NOTE: Only one index can be used in search query operation.
*
* QUERY HINTS (specified by `hints` argument):
* - $max Maximum number in the result set
* - $skip Number of skipped results in the result set
* - $orderby Sorting order of query fields.
* Eg: ORDER BY field1 ASC, field2 DESC
* hints: {
* "$orderby" : {
* "field1" : 1,
* "field2" : -1
* }
* }
*
* Many query examples can be found in `testejdb/t2.c` test case.
*
* @param EJDB database handle.
* @param qobj Main BSON query object.
* @param orqobjs Array of additional OR query objects (joined with OR predicate).
* @param orqobjsnum Number of OR query objects.
* @param hints BSON object with query hints.
* @return On success return query handle. On error returns NULL.
*/
EJDB_EXPORT EJQ* ejdbcreatequery(EJDB *jb, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints);
Examples
You can find some code samples in:
- tcejdb/samples
- tcejdb/testejdb
Basic EJDB architecture
EJDB database files structure
.
├── <dbname>
├── <dbname>_<collection1>
├── ...
├── <dbname>_<collectionN>
└── <dbname>_<collectionN>_<fieldpath>.<index ext>
Where
<dbname>
- name of database. It is metadata DB.<collectionN>
- name of collection. Collection database.<fieldpath>
- JSON field path used in index<index ext>
- Collection index extension:
.lex
String index.dec
Number index.tok
Array index
Limitations/TODOs
- Case insensitive string indexes
- Collect collection index statistic
- Windows port