Skip to content

Commit

Permalink
https is allowed; added inverseTopN and inverseRange; version bump to…
Browse files Browse the repository at this point in the history
… 0.4.0
  • Loading branch information
yuce committed Jun 10, 2017
1 parent 65d0aca commit d80e76e
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -8,5 +8,5 @@ sudo: required
services:
- docker
before_install:
- docker run -d -p 10101:10101 pilosa/pilosa:v0.3.2
- docker run -d -p 10101:10101 pilosa/pilosa:v0.4.0
script: make coveralls
15 changes: 12 additions & 3 deletions README.md
@@ -1,16 +1,25 @@
# Javascript/Typescript Client for Pilosa

<a href="https://github.com/pilosa"><img src="https://img.shields.io/badge/pilosa-v0.3.2-blue.svg"></a>
<a href="https://github.com/pilosa"><img src="https://img.shields.io/badge/pilosa-v0.4.0-blue.svg"></a>
<a href="https://www.npmjs.com/package/pilosa"><img src="https://img.shields.io/npm/v/pilosa.svg"></a>
<a href="https://travis-ci.org/yuce/js-pilosa"><img src="https://api.travis-ci.org/yuce/js-pilosa.svg?branch=master"></a>

<a href="https://coveralls.io/github/yuce/js-pilosa?branch=master"><img src="https://coveralls.io/repos/github/yuce/js-pilosa/badge.svg?branch=master"></a>

<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Cute_Sloth.jpg/320px-Cute_Sloth.jpg" style="float: right" align="right" height="180">

Javascript/Typescript client for Pilosa high performance distributed bitmap index.
Javascript/Typescript client for [Pilosa](https://www.pilosa.com/) high performance distributed bitmap index.

## Change Log

* **v0.4.0** (2017-06-10):
* Supports Pilosa Server v0.4.0.
* *Breaking Change*: Changed default row ID label to `rowID` and default column ID to `column ID`.
* Updated the accepted values for index, frame names and labels to match with the Pilosa server.
* `Union` queries accept 0 or more arguments. `Intersect` and `Difference` queries accept 1 or more arguments.
* Added `inverse TopN` and `inverse Range` calls.
* Inverse enabled status of frames is not checked on the client side.
* `https` scheme is allowed.

* **v0.3.3** (2017-05-28):
* Initial version.
* Supports Pilosa Server v0.3.2.
Expand Down
9 changes: 8 additions & 1 deletion integration-test/Client.it.ts
Expand Up @@ -230,13 +230,20 @@ describe('Client', () => {
});

it('can query topn', done => {
let frame = db.frame("topn_test");``
const sleep = (ms: number) => {
return new Promise((resolve, _) => {
setTimeout(_ => resolve(), ms);
});
}
let frame = db.frame("topn_test");
client.query(db.batchQuery(
frame.setBit(10, 5),
frame.setBit(10, 10),
frame.setBit(10, 15),
frame.setBit(20, 5),
frame.setBit(30, 5))).then(_ =>
// XXX: The following is required to make this test pass. See: https://github.com/pilosa/pilosa/issues/625
sleep(10000)).then(() =>
client.query(frame.topN(2))).then(r => {
expect(r.result).not.null;
if (r.result) {
Expand Down
4 changes: 2 additions & 2 deletions package.json
@@ -1,12 +1,12 @@
{
"name": "pilosa",
"version": "0.3.3",
"version": "0.4.0",
"description": "Javascript/Typescript client for Pilosa high performance distributed bitmap index",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"scripts": {
"test": "cross-env NODE_ENV=test mocha --recursive --compilers ts:ts-node/register --bail test/*.spec.ts",
"test-all": "cross-env NODE_ENV=test mocha --recursive --compilers ts:ts-node/register --bail --timeout 4000 test/*.spec.ts integration-test/*.it.ts",
"test-all": "cross-env NODE_ENV=test mocha --recursive --compilers ts:ts-node/register --bail --timeout 11000 test/*.spec.ts integration-test/*.it.ts",
"cover": "cross-env NODE_ENV=test nyc npm run test-all",
"generate-proto": "pbjs -t static-module -w commonjs -o internal/internal.js internal/public.proto && pbts -o internal/internal.d.ts internal/internal.js"
},
Expand Down
2 changes: 1 addition & 1 deletion src/client.ts
Expand Up @@ -243,7 +243,7 @@ export class Client {
this.currentHost = this.cluster.getHost();
}
const scheme = this.currentHost.scheme;
if (scheme != "http") {
if (scheme != "http" && scheme != "https") {
throw PilosaError.generic("Unknown scheme: " + scheme);
}
return this.currentHost;
Expand Down
41 changes: 33 additions & 8 deletions src/orm.ts
Expand Up @@ -39,13 +39,13 @@ import { PilosaError } from "./error";

export class Index {
constructor(readonly name: string, options: IndexOptions={}) {
this.columnLabel = options.columnLabel || "col_id";
this.columnLabel = options.columnLabel || "columnID";
this.timeQuantum = options.timeQuantum || TimeQuantum.NONE;
}

frame(name: string, options: FrameOptions={}) {
return _Frame.create(this, name,
options.rowLabel || "id",
options.rowLabel || "rowID",
options.timeQuantum || TimeQuantum.NONE,
options.inverseEnabled || false,
options.cacheType || CacheType.DEFAULT,
Expand Down Expand Up @@ -157,16 +157,34 @@ export class Frame {
* @return a PQL query
*/
topN(n: number, bitmap?: PqlBitmapQuery, field?: string, ...values: Array<any>): PqlBitmapQuery {
let s = `TopN(frame='${this.name}', n=${n})`;
return this._topN(n, false, bitmap, field, ...values);
}

/**
* Creates a TopN query.
*
* This variant sets inverse=true.
*
* @param bitmap the bitmap query
* @param n number of items to return
* @param field field name
* @param values filter values to be matched against the field
* @return a PQL query
*/
inverseTopN(n: number, bitmap?: PqlBitmapQuery, field?: string, ...values: Array<any>): PqlBitmapQuery {
return this._topN(n, true, bitmap, field, ...values);
}

private _topN(n: number, inverse: boolean, bitmap?: PqlBitmapQuery, field?: string, ...values: Array<any>): PqlBitmapQuery {
let s = `frame='${this.name}', n=${n}, inverse=${inverse}`;
// let s = `TopN(frame='${this.name}', n=${n})`;
if (bitmap !== undefined) {
s = `${bitmap.serialize()}, ${s}`;
if (values !== undefined && field !== undefined) {
s = `TopN(${bitmap.serialize()}, frame='${this.name}', n=${n}, field='${field}', ${JSON.stringify(values)})`;
}
else {
s = `TopN(${bitmap.serialize()}, frame='${this.name}', n=${n})`;
s = `${s}, field='${field}', ${JSON.stringify(values)}`;
}
}
return new PqlBitmapQuery(s, this.index);
return new PqlBitmapQuery(`TopN(${s})`, this.index);
}

range(rowID: number, start: Date, end: Date): PqlBitmapQuery {
Expand All @@ -176,6 +194,13 @@ export class Frame {
this.index);
}

inverseRange(columnID: number, start: Date, end: Date): PqlBitmapQuery {
const startStr = formatDateTime(start);
const endStr = formatDateTime(end);
return new PqlBitmapQuery(`Range(${this.columnLabel}=${columnID}, frame='${this.name}', start='${startStr}', end='${endStr}')`,
this.index);
}

setRowAttrs(rowID: number, attrs: AttributeMap): PqlBitmapQuery {
let attrsStr = createAttributesString(attrs);
return new PqlBitmapQuery(`SetRowAttrs(frame='${this.name}',
Expand Down
46 changes: 28 additions & 18 deletions test/orm.spec.ts
Expand Up @@ -48,43 +48,43 @@ const b4 = collabFrame.bitmap(2);
describe('Index', () => {
it('can create Union queries', () => {
const qry1 = sampleDb.union(b1, b2);
expect(qry1.serialize()).equal("Union(Bitmap(id=10, frame='sample-frame'), Bitmap(id=20, frame='sample-frame'))");
expect(qry1.serialize()).equal("Union(Bitmap(rowID=10, frame='sample-frame'), Bitmap(rowID=20, frame='sample-frame'))");

const qry2 = sampleDb.union(b1, b2, b3);
expect(qry2.serialize()).equal("Union(Bitmap(id=10, frame='sample-frame'), Bitmap(id=20, frame='sample-frame'), Bitmap(id=42, frame='sample-frame'))");
expect(qry2.serialize()).equal("Union(Bitmap(rowID=10, frame='sample-frame'), Bitmap(rowID=20, frame='sample-frame'), Bitmap(rowID=42, frame='sample-frame'))");

const qry3 = sampleDb.union(b1, b4);
expect(qry3.serialize()).equal("Union(Bitmap(id=10, frame='sample-frame'), Bitmap(project=2, frame='collaboration'))");
expect(qry3.serialize()).equal("Union(Bitmap(rowID=10, frame='sample-frame'), Bitmap(project=2, frame='collaboration'))");

const qry4 = sampleDb.union();
expect(qry4.serialize()).equal("Union()");
});

it('can create Intersect queries', () => {
const qry1 = sampleDb.intersect(b1, b2);
expect(qry1.serialize()).equal("Intersect(Bitmap(id=10, frame='sample-frame'), Bitmap(id=20, frame='sample-frame'))");
expect(qry1.serialize()).equal("Intersect(Bitmap(rowID=10, frame='sample-frame'), Bitmap(rowID=20, frame='sample-frame'))");

const qry2 = sampleDb.intersect(b1, b2, b3);
expect(qry2.serialize()).equal("Intersect(Bitmap(id=10, frame='sample-frame'), Bitmap(id=20, frame='sample-frame'), Bitmap(id=42, frame='sample-frame'))");
expect(qry2.serialize()).equal("Intersect(Bitmap(rowID=10, frame='sample-frame'), Bitmap(rowID=20, frame='sample-frame'), Bitmap(rowID=42, frame='sample-frame'))");

const qry3 = sampleDb.intersect(b1, b4);
expect(qry3.serialize()).equal("Intersect(Bitmap(id=10, frame='sample-frame'), Bitmap(project=2, frame='collaboration'))");
expect(qry3.serialize()).equal("Intersect(Bitmap(rowID=10, frame='sample-frame'), Bitmap(project=2, frame='collaboration'))");

const qry4 = sampleDb.intersect(b1);
expect(qry4.serialize()).equal("Intersect(Bitmap(id=10, frame='sample-frame'))");
expect(qry4.serialize()).equal("Intersect(Bitmap(rowID=10, frame='sample-frame'))");

expect(() => sampleDb.intersect()).throw();
});

it('can create Difference queries', () => {
const qry1 = sampleDb.difference(b1, b2);
expect(qry1.serialize()).equal("Difference(Bitmap(id=10, frame='sample-frame'), Bitmap(id=20, frame='sample-frame'))");
expect(qry1.serialize()).equal("Difference(Bitmap(rowID=10, frame='sample-frame'), Bitmap(rowID=20, frame='sample-frame'))");

const qry2 = sampleDb.difference(b1, b2, b3);
expect(qry2.serialize()).equal("Difference(Bitmap(id=10, frame='sample-frame'), Bitmap(id=20, frame='sample-frame'), Bitmap(id=42, frame='sample-frame'))");
expect(qry2.serialize()).equal("Difference(Bitmap(rowID=10, frame='sample-frame'), Bitmap(rowID=20, frame='sample-frame'), Bitmap(rowID=42, frame='sample-frame'))");

const qry3 = sampleDb.difference(b1, b4);
expect(qry3.serialize()).equal("Difference(Bitmap(id=10, frame='sample-frame'), Bitmap(project=2, frame='collaboration'))");
expect(qry3.serialize()).equal("Difference(Bitmap(rowID=10, frame='sample-frame'), Bitmap(project=2, frame='collaboration'))");

expect(() => sampleDb.difference()).throw();
});
Expand All @@ -99,7 +99,7 @@ describe('Index', () => {
describe('Frame', () => {
it('can create Bitmap queries', () => {
const qry1 = sampleFrame.bitmap(5);
expect(qry1.serialize()).equal("Bitmap(id=5, frame='sample-frame')");
expect(qry1.serialize()).equal("Bitmap(rowID=5, frame='sample-frame')");

const qry2 = collabFrame.bitmap(10);
expect(qry2.serialize()).equal("Bitmap(project=10, frame='collaboration')");
Expand All @@ -117,7 +117,7 @@ describe('Frame', () => {

it('can create SetBit queries', () => {
const qry1 = sampleFrame.setBit(5, 10);
expect(qry1.serialize()).equal("SetBit(id=5, frame='sample-frame', col_id=10)");
expect(qry1.serialize()).equal("SetBit(rowID=5, frame='sample-frame', columnID=10)");

const qry2 = collabFrame.setBit(10, 20);
expect(qry2.serialize()).equal("SetBit(project=10, frame='collaboration', user=20)");
Expand All @@ -132,28 +132,38 @@ describe('Frame', () => {

it('can create ClearBit queries', () => {
const qry1 = sampleFrame.clearBit(5, 10);
expect(qry1.serialize()).equal("ClearBit(id=5, frame='sample-frame', col_id=10)");
expect(qry1.serialize()).equal("ClearBit(rowID=5, frame='sample-frame', columnID=10)");

const qry2 = collabFrame.clearBit(10, 20);
expect(qry2.serialize()).equal("ClearBit(project=10, frame='collaboration', user=20)");
});

it('can create TopN queries', () => {
const q1 = sampleFrame.topN(27);
expect(q1.serialize()).equal("TopN(frame='sample-frame', n=27)");
expect(q1.serialize()).equal("TopN(frame='sample-frame', n=27, inverse=false)");

const q2 = sampleFrame.topN(10, collabFrame.bitmap(3));
expect(q2.serialize()).equal("TopN(Bitmap(project=3, frame='collaboration'), frame='sample-frame', n=10)");
expect(q2.serialize()).equal("TopN(Bitmap(project=3, frame='collaboration'), frame='sample-frame', n=10, inverse=false)");

const q3 = sampleFrame.topN(12, collabFrame.bitmap(7), "category", 80, 81);
expect(q3.serialize()).equal("TopN(Bitmap(project=7, frame='collaboration'), frame='sample-frame', n=12, field='category', [80,81])");
expect(q3.serialize()).equal("TopN(Bitmap(project=7, frame='collaboration'), frame='sample-frame', n=12, inverse=false, field='category', [80,81])");

const q4 = sampleFrame.inverseTopN(27);
expect(q4.serialize()).equal("TopN(frame='sample-frame', n=27, inverse=true)");

const q5 = sampleFrame.inverseTopN(12, collabFrame.bitmap(7), "category", 80, 81);
expect(q5.serialize()).equal("TopN(Bitmap(project=7, frame='collaboration'), frame='sample-frame', n=12, inverse=true, field='category', [80,81])");
});

it('can create Range queries', () => {
const start = new Date(1970, 0, 1, 0, 0);
const end = new Date(2000, 1, 2, 3, 4);
const q = collabFrame.range(10, start, end);
expect(q.serialize()).equal("Range(project=10, frame='collaboration', start='1970-01-01T00:00', end='2000-02-02T03:04')");

const q1 = collabFrame.range(10, start, end);
expect(q1.serialize()).equal("Range(project=10, frame='collaboration', start='1970-01-01T00:00', end='2000-02-02T03:04')");

const q2 = collabFrame.inverseRange(10, start, end);
expect(q2.serialize()).equal("Range(user=10, frame='collaboration', start='1970-01-01T00:00', end='2000-02-02T03:04')");
});
});

Expand Down

0 comments on commit d80e76e

Please sign in to comment.