How to get index of element in array in JSONata - jsonata

JSONata provides several functions to operate on array contents. However, I am at a loss to determine how to return the index of a found element (similar to the Array.indexOf function in JavaScript). I'm looking for something like:
$indexOf(Account.Order[OrderID="order103"])
or
Account.Order.indexOf(OrderID="order103")
or
Account.Order[OrderID="order103"].index

You could merge map's index:
Account.Order ~> $map(function($v, $i) {
$merge([{'Index': $i}, $v])
})~>function($x){$x[OrderID="order103"].Index}

Try this:
Account.Order ~> $map(function($v, $i) { $v.OrderID = 'order103' ? $i })

Neither proposed solution ensured a valid response if not found but adding the additional test seems to do what I'd expected:
($x:=Account.Order ~> $map(function($v, $i) { $v.OrderID = 'order101' ? $i });
$exists($x)?$x:-1)
will return -1
($x:=Account.Order ~> $map(function($v, $i) { $v.OrderID = 'order103' ? $i });
$exists($x)?$x:-1)
will return 0
($x:=Account.Order ~> $map(function($v, $i) { $v.OrderID = 'order104' ? $i });
$exists($x)?$x:-1)
will return 1

Accout.Order.OrderId#$i["order103" in $].$i
This is a built in way so should be faster

Related

Why does $map not output an array in case the input array is one in length?

Please check this - https://try.jsonata.org/0L_oYffzT
Here the output of the $map function is not an array.
whereas https://try.jsonata.org/Rf8UI_TMy seems to work fine when the input array is more than 1 in length.
You may use the result structure feature to accomplish this task:
var json = { "projectIds": [ 1 ] }
var result = jsonata('projectIds[].{"projectId": $}').evaluate(json);
console.log(JSON.stringify(result))
<script src="https://cdn.jsdelivr.net/npm/jsonata/jsonata.min.js"></script>
Using $map for this purpose has an open issue that point to workarounds only

laravel - access variable outside loop

my code:
$atts->each(function($row){
if($row->key == 30){
$flag = $row->value;
echo $flag;
}
});
The value of $flag will be printed to the site. However, when I try to use the variable $flag outside the loop the variable is unknown.
Can someone tell me what I am missing or what has to be done to have access to that variable?
Thanks in advance!
Regards,
Andreas
You would need to define that variable in the current scope and import that variable into your callback's scope with use.
$flag = null;
//Access flag by reference
$atts->each(function($row) use (&$flag) {
...
});
Since we're using Laravel Collections, I suggest you not use each() for this.
if ($row = $atts->where('key', 30)->first()) {
$flag = $row->value;
}
This assumes there is only one row with a key of 30 though.

Find elasticsearch indices with no aliases

I have an elasticsearch cluster whose indices I need to investigate. Specifically, I want to find all indices that do not have aliases.
Is this even possible? If so, how?
(Using sense notation for this question.)
I know I can get all indices with their aliases, even if the alias field is empty:
GET _aliases
And I know I can get all indices that have aliases:
GET /*/_alias/*
But can I get all indices without aliases?
Clearly, I can just get all indices, and then use some tool like awk or whatever to do the work for me, but my naïve guess is that it's most efficient for elasticsearch to do all this work at once.
Short answer: There is no easy api for you to find out which indices have not been linked to an alias.
Long answer: You could try the '_cluster/state' endpoint like this:
GET _cluster/state?filter_path=metadata.indices.test.aliases
Where test is the name of your index. It gives the following result:
{
"metadata": {
"indices": {
"test": {
"aliases": []
}
}
}
}
Now if I try it with an index that is actually linked:
GET _cluster/state?filter_path=metadata.indices.test_with_alias.aliases
I get the following result:
{
"metadata": {
"indices": {
"test_with_alias": {
"aliases": [
"new_alias"
]
}
}
}
}
It's not the prettiest way to do this, but it's possible :)
Hope this helps!
This shell script will help you
#!/bin/bash
ES="https://localhost:9316"
INDICES=`curl -XGET ${ES}/_cat/indices -s --insecure | awk '{print $3}'`
META=`curl -XGET "${ES}/_cluster/state?filter_path=metadata.indices.*.aliases" -s --insecure`
echo ${#META}
for INDEX in $INDICES
do
if [[ ${INDEX} != \.* ]]
then
RES=`jq ".metadata.indices.${INDEX}.aliases" <<< ${META}`
if [[ ${#RES} == 2 ]]
then
RES="NOALIAS"
fi
echo ${INDEX} $RES
fi
done
You can determine this as follows via the Java REST High Level Client:
val indexResponse = client.indices().get(GetIndexRequest("*"), RequestOptions.DEFAULT)
val aliases = indexResponse.aliases
aliases is of type Map<String, List<AliasMetadata>>. Every Map entry with a empty list (without alias metadata) is a index without an alias.
With this in mind, here's what you need to do to get all the indices without aliases.
val indicesWithoutAliases = indexResponse.aliases.filterValues { it.isEmpty() }

Bash: Reading from array

I'm writing a script in bash, and I'm trying to read from an array. When I iterate through the array with the code below:
for item in "${!functionDict[#]}"
do
echo "{ $item : ${functionDict[$item]} }" >> array.txt
done
it outputs (in "array.txt"):
{ month_start_date($year_selected, $month_selected) : return $date; }
{ logWarning($message) : return logEvent($message, $c_event_warning); }
{ daysPastLastQuarterX($curYear, $curMonth, $curDay, $selected_year, $selected_quarter, $nDays) : return false;:return false;:return false;:return false;:return true;:return $delta > $nDays; }
{ setExcelLabelCell($sheet, $cell, $label, $width) : }
{ asCurrencyString($value) : return formatCurrency($value); }
{ getNumericMonthName($m) : return $numericMonth; }
{ normalize_for_PDF(&$text) : }
However, I'm having trouble querying individual elements from the array.
I've tried:
string='month_start_date($year_selected, $month_selected)'
echo "test_output: ${functionDict[$string]}"
but I get
test_output: <blank>
I've also tried inserting some RegEx wildcards, in case there is some whitespace around the key.
echo 'size of array: '"${#functionDict[#]}"
echo "TEST: functDict[logWarning] = ${functionDict[.*'logWarning($message)'.*]}"
I get
size of array: 157 //I didn't copy/paste all the elements in the array in this post
TEST: functDict[logWarning] = <blank>
Alas, I'm stuck. The content that I'm trying to get back are the "return _" items, or just a "blank" for the keys that don't have any "return" items.
Credits to answer goes to #gniourf_gniourf. (See comments)
There was an extra leading space in all of the keys, which I hadn't included in my test queries.
(Providing an answer here so that people know this question has been solved. Hopefully this is okay practice on SO)

string as xpath selector

I have a function that takes the result set as element and a string as args and I want to use this string as a selector inside the function.
function abc ($results as element()*, $element as xs:string)
{
for $g in distinct-values($results//*[name() = $element]) (: $results//genre :)
let $c := //$results[? = $g] (: //$results[genre=$g] :)
}
what should be in place of '?' in variable '$c'
function abc ($results as element()*, $element as xs:string)
{
for $g in distinct-values($results//*[name() = $element]) (: $results//genre :)
let $c := //$results[? = $g] (: //$results[genre=$g] :)
}
what should be in place of '?' in
variable '$c'
It is a syntax error to write:
//$results
This question is rather vague, but it seems to me that you want to group the elements, contained in $results according to their genre (or whatever element name defined by $element -- BTW this name sucks (an element isn't a string) -- better use $elementName).
The other concerning fact is that you check the complete subtrees topped by each of the elements in $results -- this means that they may have multiple genre (or whatever) descendents.
To finalize my guessing spree, it seems to me that you want this:
function grouping-Keys ($elems as element()*, $subElementName as xs:string) as element()*
{
for $g in distinct-values($elems//*[name() = $subElementName ])
return
$elems[//*[name() = $subElementName ] = $g][1]
}
If it is known that $subElementName is a name of a child that any of the elements in $elems have, then the above should be better written as:
function grouping-Keys ($elems as element()*, $childElementName as xs:string) as element()*
{
for $g in distinct-values($elems/*[name() = $childElementName ])
return
$elems[/*[name() = $subElementName ] = $g][1]
}
Both of the above functions return one element per a (distinct value of) genre (or whatever). If it is known (guaranteed) that every element in $elems has exactly one child (descendent) named genre (or whatever), then the results of these functions are not redundant.

Resources