In practice, accessing JSqldb will take place through a client driver.
Typically each driver call results in one network operation (except the debug driver, see drivers). For complex queries that span more than one operation, it is recommended to create the query as a function, that can be executed in one call.
Queries declared as functions can also be stepped through using a debugger. This can be done using the synchronous debug driver.See the below example file
An additional feature of functions is that they are executed as atomic transactions.
Executing the above file in node.js, creates the function transferFunds, saves it in the db, and executes it as a test. Because it uses the debug driver, you can set breakpoints anywhere, including inside the function, and debug the code. (For example using Visual Studio Code)
Then in production, the function saved in the db can simply be executed, for example, if node.js, using the async driver:
Object key order
Unlike normal js Objects, queried Objects from JSqldb will always be returned with their keys in alphanumerical order (*unless reordered using a query function). This is because the keys are stored as such in the underlying datastore. This aids fast querying, because the keys form an index. This index can be used for fast object access, or fast range selection using query functions, similar to other storage technologies.
Working with Arrays
Both arrays and objects can be stored in JSqldb. There are a few caveats to working with arrays. Consider the following example
The above is perfectly valid, and will result in sar being a sparse array. The problem with sparse arrays is that they do not convert nicely to either an array literal or json for begin returned from the database. Therefore, if the key index needs to be preserved, JSqldb can convert an array to an object, using the tobj() function, as follows
Or taking the .where() example above
Maintaining order by constraining collection values
JSqldb provides a lot of power, ease and freedom, but with power comes responsibility. To prevent incorrect values or keys from being assigned to collections, setter functions can be specified for collections. Setter functions can for example be used to only allow objects of a specific type to be added to a collection, or only allow keys of a certain format. They can also be used to block assignment of a value altogether, or perfrom an action or query upon assignment. See .dbsetter reference.