Longo.js
Asynchronous local database with a flavor of FRP.
(Longo
means the Analects(Lunyu), in Japanese)
子曰: 学而时习之,不亦说乎
MongoDB like JavaScript Database Engine, in the local browser.
- Work in multi-thread with the power of WebWorker.
- Work at offline with embedded NoSQL-Database.
- MongoDB like APIs with underscore-query.
- Functional programming style with underscore.js
- Event-Driven and Reactive with the spilit of The Reactive Manifesto.
Architecture
+------------------+
-- ! --* Longo Collection |
/ +------------------+
/
+-------------+ +--------------+ +------------------+
| Application * -- * Longo DB * --- ! --* Longo Collection |
+-------------+ +--------------+ +------------------+
\
\ +------------------+
-- ! --* Longo Collection |
+------------------+
Dependencies
Usage
Make sure that longo.js
, longoWorker.js
, lib
is put in same directory. Default root name is Longo.js
.
This tree will be created by grunt compile
task as dest
directory.
Longo.js
├── lib
│ ├── underscore
│ │ ├── underscore-min.js
│ │ ├ ...
│ │
│ └── underscore-query
│ ├── lib
│ │ ├── underscore-query.min.js
│ │ ├ ...
│ ├ ...
│
├── longo.js
├── longo.min.js
├── longo.min.map
├── longoWorker.js
├── longoWorker.min.js
└── longoWorker.min.map
longo.js
(or longo.min.js
) underscore.js
are need to be loaded in html.
Other files will be imported at worker thread.
<script type="text/javascript" src="path/to/Longo.js/lib/underscore-min.js"></script>
<script type="text/javascript" src="path/to/Longo.js/longo.js"></script>
<script>
// Adjust root directory.
Longo.setRoot("path/to/Longo.js");
<script>
APIs
Longo is focusing to be work as like as Mongo Shell in browser world.
Because it is used in browser, Non-CRUD operation like Sharding, Replication, Auth, etcetra are not supported.
See diffrence between Mongo Shell.
Basic Example
Create database.
db = new Longo.DB("School"); db.on("error", function(e){});
Create collection and save document.
db.collection("students") .save([ {name:"st1","val":1}, {name:"st2","val":2}, {name:"st3","val":3}, {name:"st4","val":4}, {name:"st5","val":5} ]) .done(function(error){}); db.collection("teachers").insert({name:"te1","val":1}).done(function(error){}); db.collection("teachers").insert({name:"te2","val":1}).done(function(error){});
Search document from collection.
db.collection("students") .find({"count":{"$gt":3}}, {"_id":0}) .limit(3) .done(function(error, result){});
Observe style
onValue(cb, skipDuplicates)
offers observe style. Every data change in collection will be notified to observer.
var observer = db.collection("teachers") .find({"val":{"$gt":5}}) .onValue(function(error, result){console.log(result);})) // => [] db.collection("teachers") .update({"name":"te1"}, {"name":te1, value:20}) .done(); // observed query will react! // => [{"name":te1, value:20}] //kill db.killOp(observer);
Assign style
assign
is part of onValue
. Result set of data will be assigned to UI with underscore's template.
<div id="out"></div> <script type="text/template" id="resultTpl"> <ul> <% if (result && result.length > 0) { %> <% _.each(result, function(data) { %> <li id="<%= data._id %>" style="color:<%= data.color %>;"> <p> <span>| Name: <%= data.name %></span>, <span>Value: <%= data.value %></span> </p> </li> <% }); %> <% } %> </ul> </script> <script type="text/javascript"> var db = Longo.use("example"); var tpl = _.template($("#resultTpl").html()); db.collection("output").find({}).sort({"value":-1}).assign($("#out"), tpl); </script>
Promise style
promise
offers promise style. This method return thenable
object.
var p = db.collection("test").find({"promise":true}).promise(); p.then(function(result){ console.log(result); }); p.catch(function(error){ console.log(error); });
Result Dataset Receiver
All Collection methods and methods chain return Cursor object.
Cursor itself does not have and reference to result dataset.
Query will not executed until done
or onValue
or promise
, or assign
is called at the end of method chain.
When query finished, result dataset will be passed to receiver.You can use 4 type receiver as you like.
done
: Handle dataset with a given Node.js Callback style handler.onValue
: Subscribes a given handler function to dataset change. You can use dataset as stream. This feature is inspired by Bacon.js.promise
: Return Promise object. You can access dataset withthen
andcatch
method.assign
: Assign result dataset to UI with specified template.
For more detail : See Api Reference and Examples.
Query Operators
Longo use underscore-query's MongoDB like APIs for query operation.
You can use it's query for find
, update
, and remove
.
Road Map
- Next version:
- Support aggligation framework
- More tests
- Performance tuning
ver 0.2.0: Code Refactoring
- Add tests.
- Add documents.
- Refactoring code
- ver 0.1.0: Initial release
- Support basic CRUD operation
Browser Support
Longo use these native HTML5 features.
Useful polyfills is described here
Develop
Build
Longo is not released to npm, bower yet. You need build it from source.
git clone https://github.com/georgeOsdDev/longo.git cd longo npm install -g grunt-cli npm install grunt build
Deoloy
Start a web server in the
example/
folder. Hint: if you have python installed, you can just run:python -m SimpleHTTPServer
Test
With Browser
grunt connect:server:keepalive
open http://localhost:9000/test/
With Node console(Only functional module)
grunt test_cui
With PhantomJS
grunt test_phantom
Known Issue
Some case will fail with PhantomJS. So currently we run only console test with Travis.ci. If all test case passed with PhantomJS, I will change travis.ci setting to use PhantomJS.
Licence
Source code can be found on github, licenced under MIT.
Developed by Takeharu.Oshida.