Elasticsearch - Order by input options - sorting

I have an index with the following data:
{
"_index":"businesses",
"_type":"business",
"_id":"1",
"_version":1,
"found":true,
"_source":{
"business":{
"account_level_id":"2",
"business_city":"Abington",
"business_country":"United States of America",
}
}
}
When I query the index, I want to sort by account_level_id (which is a digit between 1-5). The problem is, I don't want to sort in ASC or DESC order, but by the following: 4..3..5..2..1. This was caused by bad practice a couple years ago, where the account level maxed out at level 4, but then a lower level account was added with the value of 5. Is there a way to tell ES that I want the results returned in that specific order?

You could write a sort based script something like (not tested):
doc['account_level_id'].value == "5" ? 3 : doc['account_level_id'].value == "4" ? 5 : doc['account_level_id'].value == "3" ? 4 : doc['account_level_id'].value == "2" ? 2 : 1;
Or if possible you could create another field sort_level that maps account_level_id to sensible values that you can sort on.
{
"_index":"businesses",
"_type":"business",
"_id":"1",
"_version":1,
"found":true,
"_source":{
"business":{
"account_level_id":"4",
"business_city":"Abington",
"business_country":"United States of America",
"sort_level": 5
}
}
}

If you can sort in DESC you can create function that maps integers and sort using it.
DESC should sort them like (5 4 3 2 1), 5 replaced by 4, 4 replaced by 3, 3 replaced by 5.
int map_to(int x){
switch(x){
case 1: case 2: return x;
case 3: return 4;
case 4: return 5;
case 5: return 3;
}
}
and use it for your sorting algorithm (so when sorting algorithm has to compare x vs y it should compare map_to(x) vs map_to(y) , and this will make 4 comes before 3 and 5 as you want.

Related

amount of character which are between epiosde 1 and 2 with the name Rick

I have a problem. I am using the https://rickandmortyapi.com/graphql API for graphql. I want to query the amount of character which are between epiosde 1 and 2 with the name Rick. Unfortunately my query is wrong. How could I get the desired output. I want to use the _" ..."Meta to get the meta data.
query {
characters(filter: {name: "Rick"}) {
_episode(filter: {id : 1
id: 2}) {
count
}
}
}

Check if input is in range. HASURA - GRAPHQL

I would like to check if a number is in a specific range dynamically. For example i have a table like:
id
value
age_range
1
a
3-7
2
b
7-10
3
c
3-7
4
d
0-3
if the age of the user is 5, i would like to retrieve all rows where age_range is 3-7 without writing the range in the where clause query. For example something like:
table (where: { 5 in age_range })...
Make an age_from and an age_to column if possible.
query MyQuery($int: Int!) {
table(where: {_and: [{age_to: {_gte: $int}}, {age_from: {_lte: $int}}]}) {
#Fields....
}
}

Summarise nested fields

I'm having a hard time getting a specific query right.
I have a schema following this style:
{
"User": "user1" ,
"active": true ,
"points": {
"2015-07": 2 ,
"2015-08": 5 ,
"2015-09": 7 ,
"2015-10": 1 ,
"2015-11": 28 ,
"2015-12": 5 ,
"2016-01": 3
}
}
{
"User": "user2" ,
"active": true ,
"points": {
"2015-01": 8 ,
"2015-02": 4 ,
"2015-09": 6 ,
"2015-10": 12 ,
"2015-11": 34 ,
"2015-12": 1 ,
"2016-01": 2
}
}
How can I write a query that will return each user and the total amount of points?
Just a small typo in #Tryneus' example, .sum(...) should go at the end. Try this one:
r.db('test').table('test').map(function (x) {
return x.merge( {points: x('points').values().sum()})
})
For those of us unfortunate enough to still be stuck with a version of RethinkDB without a values function, the trick is to first retrieve all keys and use map to retrieve a sequence of values:
r.db("test").table("test").map(function (x) {
return x.merge({
points: x("points").keys().map(function(key) {
return x("points")(key)
}).sum()
})
})
It should be simple enough to do this with a map, summing the values of the "points" object in each row. This code is in Javascript, so it should work in the Data Explorer, where r.expr(data) is the sequence of values you want to operate on.
r.expr(data).map(function (x) {
return x.merge({points:r.sum(x('points').values())});
})

How to do natural sort/alpha numeric sort over columns for y-dimension in jqGrid pivot table

For columns in y-dimension how to do natural sort for alpha numeric column names ?
For example:
consider column names AA1, AA2, AA3, AA10, AA11.
These are listed in order AA1, AA10, AA11, AA2, AA3 in pivot table y-dimension.
Desired order of columns is AA1, AA2, AA3, AA10, AA11
Free jqGrid 4.9 contains full rewritten version of jqPivot. I tried to hold compatibility with the previous version, but it contains many advanced features. I tried to describe there in wiki.
Not so many people uses jqPivot. So I remind what it do. It gets an input data as source and generate new data, which will be input data for jqGrid. Additionally jqPivot generates colModel based on input data and yDimension parameter. During analyzing of input data jqPivot sorts input data by xDimension and by yDimension. The order or sorting of xDimension defines the order of rows of resulting grid. The order or sorting of yDimension defines the order of columns of resulting grid and the total number of resulting columns. The options compareVectorsByX and compareVectorsByY of allows to specify callback function which will be used for custom sorting by the whole x or y vector. It's important to understand that sorting function not only specify the the order of columns, but it informs jqPivot which vectors should be interpreted as the same. For example it can interpret the values 12, 12.0 and 012.00 as the same and specify that 12.0 is larger as 6.
I describe below some ways which can be used to customize sorting by xDimension and yDimension.
First of all one can specify skipSortByX: true or skipSortByY: true parameters. In the case the input data have to be already sorted in the order which you want. The next important options are Boolean options caseSensitive (with default value false) and trimByCollect (default value true). caseSensitive: true can be used to distinguish input data by case and trimByCollect: false can be used to hold trailing spaces in the input data.
Some other important option can be specified in xDimension or yDimension: sorttype and sortorder. sortorder: "desc" can be used to reverse the order of sorted data. The option sorttype can be "integer" (or "int") which means to truncate (Math.floor(Number(inputValue))) input data during sorting; The values "number", "currency" and "float" means that the input data should be converted to numbers during sorting (Number(inputValue)). Finally one can don't specify any sorttype, but specify compare callback function instead. The compare callback is function with two parameters and it should return well known -1, 0 or 1 values.
For example I created the demo for one issue. One asked my about the following situation. The web site contains login, which identifies the country of the user. One want to set the user's country as the first in the sorting order. The demo uses the following yDimension parameter:
yDimension: [
{ dataName: "sellyear", sorttype: "integer" },
{ dataName: "sell month",
compare: function (a, b) {
if (a === "Germany") { return b !== "Germany" ? -1 : 0; }
if (b === "Germany") { return 1; }
if (a > b) { return 1; }
if (a < b) { return -1; }
return 0;
}}
]
It sets "Germany" first in the sorting order. As the results one sees the results like on the picture below
You can use the same approach using the code for natural compare from the answer and you will implements your requirements.
In more advanced cases one can use the options compareVectorsByX and compareVectorsByY. The requirement was to place specific country only in one specific year on the first place holding the standard order on all other cases. The corresponding demo uses compareVectorsByY to implement the requirement. It displays
and uses the following compareVectorsByY:
compareVectorsByY: function (vector1, vector2) {
var fieldLength = this.fieldLength, iField, compareResult;
if (fieldLength === 2) {
if (vector1[0] === "2011" && vector1[1] === "Germany") {
if (vector2[0] === "2011" && vector2[1] === "Germany") {
return {
index: -1,
result: 0
};
}
return {
index: vector2[0] === "2011" ? 1 : 0,
result: -1
};
}
// any vector1 is larger as vector2 ("2011", "Germany")
if (vector2[0] === "2011" && vector2[1] === "Germany") {
return {
index: vector2[0] === "2011" ? 1 : 0,
result: 1
};
}
}
for (iField = 0; iField < fieldLength; iField++) {
compareResult = this.fieldCompare[iField](vector1[iField], vector2[iField]);
if (compareResult !== 0) {
return {
index: iField,
result: compareResult
};
}
}
return {
index: -1,
result: 0
};
}
It's important to mention that compareVectorsByY callback function should return object with two properties: index and result. The value of result property should be -1, 0 or 1. The value of index property should be -1 in case of result: 0 and be 0-based index of vectors where vector1 and vector2 are different.

table() add and remove values

I'm trying to create an efficient table() calculation (get the frequency of each value in a vector). The difference from the ordinary table() function is that it needs to support adding and removing values without recalculating the whole table.
I thought of using a hash table. for add: look for the key, add 1 to the value. for remove: look for the key. if found: subtract 1 from value, if not found: add new key with value=1.
I was wondering if any of you have other ideas.
Example:
X
key freq
1 3
2 5
3 2
8 1
remove(8)
key freq
1 3
2 5
3 2
add(2)
key freq
1 3
2 6
3 2
Any ideas for an efficient implementation?
Thanks in advance!
--EDIT--
My current code, if anyone is interested (also involves the calculation of shannon entropy)
create.freq.hash<-function(x)
{
t<-table(x)
h<-hash(names(t),as.numeric(t));
return(h);
}
freq.hash.add<-function(hash,key)
{
if(is.null(hash[[key]]))
{
.set(hash,key,+1)
}
else
{
.set(hash,key,hash[[key]]+1)
}
}
freq.hash.remove<-function(hash,key)
{
if(!is.null(hash[[key]]))
{
if(hash[[key]]==1)
del(key,hash)
else
.set(hash,key,hash[[key]]-1)
}
}
hash.entropy<-function(hash)
{
if(is.empty(hash))
return;
v<-values(hash);
v.prob<-v/sum(v);
entropy = (-1)*(v.prob%*%log2(v.prob))
return(entropy)
}

Resources