Index

Longo.js Build Status

Asynchronous local database with a flavor of FRP. (Longo means the Analects(Lunyu), in Japanese)

子曰: 学而时习之,不亦说乎

MongoDB like JavaScript Database Engine, in the local browser.

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 with then and catch 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

  1. 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

  1. Start a web server in the example/ folder. Hint: if you have python installed, you can just run:

    python -m SimpleHTTPServer

  2. Browse http://localhost:8000/example/todomvc/

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.