nLinq queries are made through a series of calls divided into three main areas:
var result = $from( aSourceArray ) // FROM part
.equals("aKey1", aValue) // WHERE part
.greater("aKey2", 10) //
.select() // SELECT part
Listed below, there are different combinations of WHERE and SELECT functions that you can use.
The input should be primarially an array. If a map is provided it will be converted into an array. For streams it can also be a function.
var inData = [ 1, 2, 3 ];
var outData = $from(inData).select();
// [ 1, 2, 3 ]
var inData = [ { a: 1 }, { a: 2 }, { a: 3 } ];
var outData = $from(inData).select();
// [ {a: 1}, {a: 2}, {a: 3} ]
var inData = { a: 1, b: 2, c: 3};
var outData = $from(inData).select();
// [ 1, 2, 3 ]
var inData = { a1: { a: 1 }, a2: { a: 2 }, a3: { a: 3 } };
var outData = $from(inData).select();
// [ { a: 1, _key: "a1" }, { a: 2, _key: "a2" }, { a: 3, _key: "a3"} ]
You can specify the key name (instead of "_key") by adding an extra parameter:
var inData = { a1: { a: 1 }, a2: { a: 2 }, a3: { a: 3 } };
var outData = $from(inData).select();
// [ { a: 1, b: "a1" }, { a: 2, b: "a2" }, { a: 3, b: "a3"} ]
var ll = 0, sum = 0;
var fn = () => ll++;
$from(fn).limit(5).stream(r => sum += r);
// sum = 10 | ll = 6
Consider the following example:
var names = [
{ first: "James", last: "Bond" },
{ first: "James", last: "Scott" },
{ first: "Louis", last: "Bond" }
];
Method | Description | Example |
---|---|---|
starts | Restricts string fields prefix to a value | $from(names).starts("first", "J").select() [{"first":"James","last":"Bond"},{"first":"James","last":"Scott"}] |
andStarts | Restricts string fields prefix to a value in addition to the previous restriction | $from(names).starts("first", "J").starts("last", "B").select() [{"first":"James","last":"Bond"}] |
notStarts | Restricts string fields that are not prefixed by a value | $from(names).notStarts("first", "J").select() [{"first":"Louis","last":"Bond"}] |
andNotStarts | Restricts string fields that are not prefixed by a value in addition to the previous restriction | $from(names).starts("first", "J").andNotStarts("last", "S").select() [{"first":"James","last":"Bond"}] |
orStarts | Restricts string fields prefix to a value in alternative to the previous restriction | $from(names).starts("first", "Ja").orStarts("last", "Bo").select() [{"first":"James","last":"Bond"},{"first":"James","last":"Scott"},{"first":"Louis","last":"Bond"}] |
orNotStarts | Restricts string fields prefix that are not prefixed by a value in alternative to the previous restriction | $from(names).starts("first", "Ja").orNotStarts("last", "Sc").select() [{"first":"James","last":"Bond"},{"first":"James","last":"Scott"},{"first":"Louis","last":"Bond"}] |
ends | Restricts string fields suffix to a value | $from(names).ends("last", "nd").select() [{"first":"James","last":"Bond"},{"first":"Louis","last":"Bond"}] |
andEnds | Restricts string fields suffix to a value in addition to the previous restriction | $from(names).ends("first", "es").andEnds("last", "d").select() [{"first":"James","last":"Bond"}] |
notEnds | Restricts string fields that are not suffixed by a value | $from(names).notEnds("last", "Bond").select() [{"first":"James","last":"Scott"}] |
andNotEnds | Restricts string fields that are not suffixed by a value in addition to a previous restriction | $from(names).starts("first", "J").andNotEnds("last", "d").select() [{"first":"James","last":"Scott"}] |
orEnds | Restricts string fields that are suffixed by a value in alternative to a previous restriction | $from(names).starts("first", "J").orEnds("first", "d").select() [{"first":"James","last":"Bond"},{"first":"James","last":"Scott"}] |
orNotEnds | Restricts string fields that are not suffixed by a value in alternative to a previous restriction | $from(names).starts("first", "J").orNotEnds("first", "s").select() [{"first":"James","last":"Bond"},{"first":"James","last":"Scott"}] |
Method | Description | Example |
---|---|---|
andEquals | Restricts by a specific value of a field | $from(names).equals("firstName", "Scoot").andEquals("lastName", "Tiger").select() |
greaterEquals | Restricts by a field value greater than or equal to a specific value | $from(names).greaterEquals("age", 30).select() |
andGreaterEquals | Restricts by multiple field values greater than or equal to specific values | $from(names).greaterEquals("age", 30).andGreaterEquals("salary", 50000).select() |
notGreaterEquals | Restricts by a field value not greater than or equal to a specific value | $from(names).notGreaterEquals("age", 30).select() |
andNotGreaterEquals | Restricts by multiple field values not greater than or equal to specific values | $from(names).notGreaterEquals("age", 30).andNotGreaterEquals("salary", 50000).select() |
orGreaterEquals | Restricts by either of the field values being greater than or equal to specific values | $from(names).greaterEquals("age", 30).orGreaterEquals("salary", 50000).select() |
orNotGreaterEquals | Restricts by either of the field values not being greater than or equal to specific values | $from(names).notGreaterEquals("age", 30).orNotGreaterEquals("salary", 50000).select() |
lessEquals | Restricts by a field value less than or equal to a specific value | $from(names).lessEquals("age", 30).select() |
andLessEquals | Restricts by multiple field values less than or equal to specific values | $from(names).lessEquals("age", 30).andLessEquals("salary", 50000).select() |
andNotLessEquals | Restricts by multiple field values not less than or equal to specific values | $from(names).notLessEquals("age", 30).andNotLessEquals("salary", 50000).select() |
orLessEquals | Restricts by either of the field values being less than or equal to specific values | $from(names).lessEquals("age", 30).orLessEquals("salary", 50000).select() |
orNotLessEquals | Restricts by either of the field values not being less than or equal to specific values | $from(names).notLessEquals("age", 30).orNotLessEquals("salary", 50000).select() |
Method | Description | Example |
---|---|---|
greater | Restricts by a field value greater than a specific value | $from(names).greater("age", 30).select() |
andGreater | Restricts by multiple field values greater than specific values | $from(names).greater("age", 30).andGreater("salary", 50000).select() |
notGreater | Restricts by a field value not greater than a specific value | $from(names).notGreater("age", 30).select() |
andNotGreater | Restricts by multiple field values not greater than specific values | $from(names).notGreater("age", 30).andNotGreater("salary", 50000).select() |
orGreater | Restricts by either of the field values being greater than specific values | $from(names).greater("age", 30).orGreater("salary", 50000).select() |
orNotGreater | Restricts by either of the field values not being greater than specific values | $from(names).notGreater("age", 30).orNotGreater("salary", 50000).select() |
less | Restricts by a field value less than a specific value | $from(names).less("age", 30).select() |
andLess | Restricts by multiple field values less than specific values | $from(names).less("age", 30).andLess("salary", 50000).select() |
notLess | Restricts by a field value not less than a specific value | $from(names).notLess("age", 30).select() |
andNotLess | Restricts by multiple field values not less than specific values | $from(names).notLess("age", 30).andNotLess("salary", 50000).select() |
orLess | Restricts by either of the field values being less than specific values | $from(names).less("age", 30).orLess("salary", 50000).select() |
orNotLess | Restricts by either of the field values not being less than specific values | $from(names).notLess("age", 30).orNotLess("salary", 50000).select() |
between | Restricts by a field value between two specific values | $from(names).between("age", 20, 30).select() |
andBetween | Restricts by multiple field values between specific values | $from(names).between("age", 20, 30).andBetween("salary", 40000, 60000).select() |
andNotBetween | Restricts by multiple field values not between specific values | $from(names).notBetween("age", 20, 30).andNotBetween("salary", 40000, 60000).select() |
orBetween | Restricts by either of the field values being between specific values | $from(names).between("age", 20, 30).orBetween("salary", 40000, 60000).select() |
orNotBetween | Restricts by either of the field values not being between specific values | $from(names).notBetween("age", 20, 30).orNotBetween("salary", 40000, 60000).select() |
betweenEquals | Restricts by a field value between or equal to two specific values | $from(names).betweenEquals("age", 20, 30).select() |
andBetweenEquals | Restricts by multiple field values between or equal to specific values | $from(names).betweenEquals("age", 20, 30).andBetweenEquals("salary", 40000, 60000).select() |
andNotBetweenEquals | Restricts by multiple field values not between or equal to specific values | $from(names).notBetweenEquals("age", 20, 30).andNotBetweenEquals("salary", 40000, 60000).select() |
orBetweenEquals | Restricts by either of the field values being between or equal to specific values | $from(names).betweenEquals("age", 20, 30).orBetweenEquals("salary", 40000, 60000).select() |
orNotBetweenEquals | Restricts by either of the field values not being between or equal to specific values | $from(names).notBetweenEquals("age", 20, 30).orNotBetweenEquals("salary", 40000, 60000).select() |
Method | Description | Example |
---|---|---|
contains | ||
andContains | ||
andNotContains | ||
orContains | ||
orNotContains | ||
empty | ||
andEmpty | ||
andNotEmpty | ||
orEmpty | ||
orNotEmpty | ||
match | ||
andMatch | ||
andNotMatch | ||
orMatch | ||
orNotMatch |
Method | Description | Example |
---|---|---|
type | ||
andType | ||
andNotType | ||
orType | ||
orNotType |
Method | Description | Example |
---|---|---|
is | ||
andIs | ||
andNotIs | ||
orIs | ||
orNotIs | ||
or | ||
and | ||
not | ||
andNot | ||
orNot |
Method | Description | Example |
---|---|---|
each | ||
intersect | ||
except | ||
union | ||
cartesian | ||
attach | ||
sort | ||
assign | ||
join | ||
skip | ||
take | ||
skipTake | ||
define | ||
removed | ||
stream | ||
streamFn |
Method | Description | Example |
---|---|---|
select | Returns all fields from the original array | $from(anArray).select() |
select (selected fields) | Returns specific fields with corresponding default values | $from(anArray).select({ f1: "n/a", f2: false }) |
select (transform function) | Returns the result of the transformation function | $from(anArray).select(r => ({ f1: r.f1, f2: r.a1 + r.a2 })) |
min | Returns the minimum value of a field from the result | $from(anArrayOfTemperatures).min("temperature") |
max | Returns the maximum value of a field from the result | $from(anArrayOfTemperatures).max("temperature") |
average | Returns the average value of a field from the result | $from(anArrayOfTemperatures).average("temperature") |
sum | Returns the sum value of a field from the result | $from(anArrayOfFiles).sum("size") |
distinct | Returns an array of distinct values for a specific field from the result | $from(anArrayOfMeasures).distinct("measureName") |
group | Returns a map grouping the array of records by a specific field from the result | $from(anArrayOfTemperatures).group("city") |
at | Returns a single entry of the result set | $from(anArray).at(23) |
all | Returns true if all records from the original array are present on the final result set (false otherwise) | $from(anArray).all() |
count | Returns the number of records of the final result set | $from(anArray).count() |
countBy | Returns an array counting records per each value after grouping the array of records by a specific field from the result | $from(anArray).countBy("groupByFieldName1,groupByFieldName2", "countRecordsFieldName", "keyFieldNameToUseOnResult1,keyFieldNameToUseOnResult2") |
first | Returns the first record of the final result set | $from(anArray).first() |
last | Returns the last record of the final result set | $from(anArray).last() |
any | Returns true if the result set has any record at all (false otherwise) | $from(anArray).any() |
none | Returns true if the result set is empty (false otherwise) | $from(anArray).none() |
reverse | Returns a reverse order result set | $from(anArray).reverse() |
limit | Returns just a limited amount of records of the result set | $from(anArray).limit(5) |
head | Returns a limited amount of the first records of the result set | $from(anArray).head(10) |
tail | Returns a limited amount fo the last records of the result set | $from(anArray).tail(10) |
Return the current result set with the WHERE part applied:
var result = $from([ 1, 2, 3 ]).select();
// [ 1, 2, 3 ]
Return the current result set with the WHERE part restricting each map entry on the result to the fields provided and their default values in case they are not present:
var inData = [
{ name: "Point 1", x: 1, y: -1 },
{ name: "Point 2", x: 5, y: -5 },
{ x: 3 }
];
var result = $from(inData).select({ x: 0, y: 0 });
// [ { x: 1, y: -1 },
// { x: 5, y: -5 },
// { x: 3, y: 0 } ]
The result set will be transformed by the provided function:
var inData = [
{ name: "Vector 1", x1: 2, y1: -1, x2: 5, y2: -10 },
{ name: "Vector 2", x1: -2, y1: -1, x2: 5, y2: 10 }
];
var result = $from(inData).select(r => {
var newResult = { name: r.name };
newResult.distance = Math.round( Math.sqrt( Math.pow(r.x1-r.x2, 2) + Math.pow(r.y1-r.y2, 2)));
return newResult;
});
// [ { name: "Vector 1", distance: 9 },
// { name: "Vector 2", distance: 13} ]
The result set can be transformed into a map of maps by provided an index field:
var inData = [ { a: 1, b: "a1" }, { a: 2, b: "a2" }, { a: 3, b: "a3" } ];
var outData = $from(inData).select(void 0, "b");
// { "a1": {"a":1,"b":"a1"}, "a2": {"a":2,"b":"a2"}, "a3":{"a":3,"b":"a3"} }
It's also possible to provide all the query as a map instead of method calls. To do this you can use:
var result = $from(anArrayOfData).query(aQueryMap)
The query map to provide to the query method is composed of 3 or 4 parts depending on the use:
aQueryMap = { where: [], transform: [], select: {} }
// or
aQueryMap = { where: [], transform: [], selector: {} }
The following example is provided in YAML with comments to make it easier to visualize:
# 1. The where part is composed of an array of conditions and arguments that limit the data
where:
## This is the same as doing .equals("isFile", true)
- cond: equals
args:
- isFile
- true
# 2. The transform part is composed of an array of functions and arguments that transform the data
transform:
## These are the same as doing .attach("lastAccess", elem => new Date(elem.lastAccess)).sort("-size")
- func: attach
args:
- lastAccess
- !!js/eval elem => new Date(elem.lastAccess)
- func: sort
args:
- "-size"
# 3. The select part if composed of the same map you would provide to a .select method
## This is equivalent to .select({ filename: "n/a", size: -1 })
select:
filename: n/a
size : -1
# 4. The selector part as an alternative to part 3 allows the use of selector functions
## selector:
### This is equivalent to .at(0)
## func: at
## args:
## - 0
NOTE: As you can see each part (with the exception of select) is always an array of maps or a single map with a function name (cond/func) followed by an array of the corresponding arguments (args). There are no restrictions on the functions you should use on where or transform. The only difference between where/transform and select/selector is that select/selector are functions that cannot be chained and will return a result.
In the end this yaml could be provided as a JSON map to the query method like this:
aQueryMap = { where: [ { cond: "equals", args: [ "isFile", true ] } ], transform: [ { func: "attach", args: [ "lastAccess", elem => new Date(elem.lastAccess) }, { func: "sort", args: "-size" ], select: { filename: "n/a", size: -1 } }
Translation: Will filter an array of map for the entries where the field isFile is true, will add/replace the field attach converting it into a javascript Date, then sort the resulting array by biggest values on the field size (descending order) and returning an array of maps as a result with two fields: filename and size. If filename is not defined for some entry it will be represented as "n/a"; if size is not defined for some entry it will be represented as -1.
Similary using a selector the JSON map to the query method would look like:
aQueryMap = { where: [ { cond: "equals", args: [ "isFile", true ] } ], transform: [ { func: "attach", args: [ "lastAccess", elem => new Date(elem.lastAccess) }, { func: "sort", args: "-size" ], selector: { func: "at", args: [ 0 ] } }
Translation: Will filter an array of map for the entries where the field isFile is true, will add/replace the field attach converting it into a javascript Date, then sort the resulting array by biggest values on the field size (descending order) and returning only the map, on position 0, of the resulting array of maps.