Comparing version 0.2.0 to 0.4.0
@@ -6,2 +6,3 @@ var EventEmitter = require('events').EventEmitter; | ||
var nop = require('nop'); | ||
var roughMatch = require('./genotypeMatch'); | ||
@@ -18,2 +19,3 @@ function Query(opt){ | ||
// all allele match | ||
Query.prototype.exact = function(id, genotype){ | ||
@@ -24,3 +26,3 @@ if (!id) throw new Error("Missing id in 'exact' query"); | ||
this.add(function(snp, cb){ | ||
cb(null, (snp.id === id && snp.g === genotype)); | ||
cb(null, (snp.id === id && roughMatch(snp.g, genotype))); | ||
}); | ||
@@ -30,2 +32,13 @@ return this; | ||
Query.prototype.exactNot = function(id, genotype){ | ||
if (!id) throw new Error("Missing id in 'exactNot' query"); | ||
if (!genotype) throw new Error("Missing genotype in 'exactNot' query"); | ||
this.add(function(snp, cb){ | ||
cb(null, (snp.id === id && !roughMatch(snp.g, genotype))); | ||
}); | ||
return this; | ||
}; | ||
// one allele match | ||
Query.prototype.has = function(id, genotype){ | ||
@@ -41,7 +54,8 @@ if (!id) throw new Error("Missing id in 'has' query"); | ||
Query.prototype.doesntExist = function(id){ | ||
if (!id) throw new Error("Missing id in 'doesntExist' query"); | ||
Query.prototype.hasNot = function(id, genotype){ | ||
if (!id) throw new Error("Missing id in 'hasNot' query"); | ||
if (!genotype) throw new Error("Missing genotype in 'hasNot' query"); | ||
this.add(function(snp, cb){ | ||
cb(null, (snp.id === id && !snp.g)); | ||
cb(null, (snp.id === id && (!snp.g || snp.g.indexOf(genotype) === -1))); | ||
}); | ||
@@ -51,2 +65,3 @@ return this; | ||
// any allele match | ||
Query.prototype.exists = function(id){ | ||
@@ -61,8 +76,7 @@ if (!id) throw new Error("Missing id in 'exists' query"); | ||
Query.prototype.exactNot = function(id, genotype){ | ||
if (!id) throw new Error("Missing id in 'exactNot' query"); | ||
if (!genotype) throw new Error("Missing genotype in 'exactNot' query"); | ||
Query.prototype.doesntExist = function(id){ | ||
if (!id) throw new Error("Missing id in 'doesntExist' query"); | ||
this.add(function(snp, cb){ | ||
cb(null, (snp.id === id && snp.g !== genotype)); | ||
cb(null, (snp.id === id && !snp.g)); | ||
}); | ||
@@ -72,18 +86,25 @@ return this; | ||
Query.prototype.hasNot = function(id, genotype){ | ||
if (!id) throw new Error("Missing id in 'hasNot' query"); | ||
if (!genotype) throw new Error("Missing genotype in 'hasNot' query"); | ||
this.add(function(snp, cb){ | ||
cb(null, (snp.id === id && (!snp.g || snp.g.indexOf(genotype) === -1))); | ||
// grouping queries | ||
Query.prototype.or = function(){ | ||
var args = [].slice.apply(arguments); | ||
var afns = args.map(function(q){ | ||
return q._conditions.pop(); | ||
}); | ||
return this; | ||
}; | ||
Query.prototype.exact = function(id, genotype){ | ||
if (!id) throw new Error("Missing id in 'exact' query"); | ||
if (!genotype) throw new Error("Missing genotype in 'exact' query"); | ||
this.add(function(snp, cb){ | ||
cb(null, (snp.id === id && snp.g === genotype)); | ||
var fns = afns.slice(0); | ||
var matched = false; | ||
var isDone = function(){ | ||
return matched === true || fns.length === 0; | ||
}; | ||
var next = function(done){ | ||
fns.shift()(snp, function(err, isMatch){ | ||
if (err) return done(err); | ||
matched = isMatch; | ||
done(); | ||
}); | ||
}; | ||
async.until(isDone, next, function(err){ | ||
cb(err, matched); | ||
}); | ||
}); | ||
@@ -93,6 +114,5 @@ return this; | ||
// this is kind of a hack... | ||
Query.prototype.or = function(){ | ||
Query.prototype.and = function(){ | ||
var args = [].slice.apply(arguments); | ||
var fns = args.map(function(q){ | ||
var afns = args.map(function(q){ | ||
return q._conditions.pop(); | ||
@@ -102,5 +122,7 @@ }); | ||
this.add(function(snp, cb){ | ||
var matched = false; | ||
var fns = afns.slice(0); | ||
var matched = true; | ||
var isDone = function(){ | ||
return matched === true || fns.length === 0; | ||
return matched === false || fns.length === 0; | ||
}; | ||
@@ -121,2 +143,3 @@ var next = function(done){ | ||
// base functions | ||
Query.prototype.add = function(fn) { | ||
@@ -132,3 +155,2 @@ this._conditions.push(fn); | ||
// task system | ||
Query.prototype.needs = function(num){ | ||
@@ -135,0 +157,0 @@ this._needs = num; |
{ | ||
"name":"gql", | ||
"description":"Query language for interpreting genome SNPs", | ||
"version":"0.2.0", | ||
"homepage":"http://github.com/genomejs/gql", | ||
"repository":"git://github.com/genomejs/gql.git", | ||
"author":"Fractal <contact@wearefractal.com> (http://wearefractal.com/)", | ||
"main":"./index.js", | ||
"tags": ["genomejs", "genoset", "gs144", "dna", "genetics", "genes", "query", "language"], | ||
"dependencies":{ | ||
"event-stream":"*", | ||
"async":"*", | ||
"nop":"*" | ||
}, | ||
"devDependencies":{ | ||
"mocha":"*", | ||
"should":"*" | ||
}, | ||
"scripts":{ | ||
"test":"mocha" | ||
}, | ||
"engines":{ | ||
"node":">= 0.4.0" | ||
}, | ||
"licenses":[ | ||
{ | ||
"type":"MIT", | ||
"url":"http://github.com/genomejs/gql/raw/master/LICENSE" | ||
} | ||
] | ||
"name": "gql", | ||
"description": "Query language for interpreting genome SNPs", | ||
"version": "0.4.0", | ||
"homepage": "http://github.com/genomejs/gql", | ||
"repository": "git://github.com/genomejs/gql.git", | ||
"author": "Fractal <contact@wearefractal.com> (http://wearefractal.com/)", | ||
"main": "./index.js", | ||
"tags": [ | ||
"genomejs", | ||
"genoset", | ||
"gs144", | ||
"dna", | ||
"genetics", | ||
"genes", | ||
"query", | ||
"language" | ||
], | ||
"dependencies": { | ||
"event-stream": "*", | ||
"async": "*", | ||
"nop": "*" | ||
}, | ||
"devDependencies": { | ||
"mocha": "*", | ||
"should": "*" | ||
}, | ||
"scripts": { | ||
"test": "mocha" | ||
}, | ||
"engines": { | ||
"node": ">= 0.4.0" | ||
}, | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "http://github.com/genomejs/gql/raw/master/LICENSE" | ||
} | ||
] | ||
} |
@@ -88,3 +88,3 @@ [![Build Status](https://travis-ci.org/genomejs/gql.png?branch=master)](https://travis-ci.org/genomejs/gql) | ||
Creates a new GQL chainable query | ||
Creates a new GQL chainable query. Keep in mind that each condition is tested against one SNP at a time. If the condition is met then it is marked as a match and not tested again. | ||
@@ -124,2 +124,18 @@ #### exact(id, genotype) | ||
#### or(conditions...) | ||
Evaluates to true if any of the argument conditions evaluates to true | ||
```javascript | ||
q.or(q.has("rs2032651", "A"), q.doesntExist("rs2032651")); | ||
``` | ||
#### and(conditions...) | ||
Evaluates to true if all of the argument conditions evaluates to true | ||
```javascript | ||
q.and(q.exists("rs2032651"), q.has("rs2032651", "A")); | ||
``` | ||
#### add(fn) | ||
@@ -126,0 +142,0 @@ |
@@ -36,2 +36,17 @@ var gql = require('../'); | ||
it('should return a working query that matches roughly', function(done) { | ||
var sample = {id: "test", g: "AB"}; | ||
var query = gql.query(); | ||
query.exact("test", "BA"); | ||
query.process(sample, function(err){ | ||
should.not.exist(err); | ||
query.matches().length.should.equal(1); | ||
query.matches().should.eql([sample]); | ||
query.unmatched().length.should.equal(0); | ||
done(); | ||
}); | ||
}); | ||
it('should return a working query with multiple statements', function(done) { | ||
@@ -38,0 +53,0 @@ var sample = {id: "test", g: "A"}; |
@@ -24,2 +24,3 @@ var gql = require('../'); | ||
faked.push({id:"rs2032651", g:"D"}); | ||
faked.push({id:"rs2032652", g:"AG"}); | ||
@@ -41,5 +42,6 @@ var query = gql.query(); | ||
query.or(query.exact("rs17222419", "C"), query.exact("rs17222419", "T")); | ||
query.and(query.exact("rs2032652", "AG"), query.has("rs2032652", "G")); | ||
es.readArray(faked).pipe(query.stream()).on('end', function(){ | ||
query.matches().length.should.equal(1); | ||
query.matches().length.should.equal(2); | ||
query.matches().should.eql(faked); | ||
@@ -46,0 +48,0 @@ query.unmatched().length.should.equal(13); |
26659
11
587
205
4