Nesting OR statements within AND statements using Funnelback query parameters - search

I'm trying to insert OR statements within some AND statements on my search and am having trouble nailing down the operators I need to use.
What I'm essentially trying to do is state the following (cue the pseudo)
query = "nematode" && (meta_M == "North" || meta_M == "South") && (meta_N == "Category value 1" || meta_N == "Category value 2")
My attempts seem to have been generating wide OR statements which inflates my initial query for nematode (425 results) into 1,000+ results instead of reducing it to a sub-set of the original results.
I've consulted http://docs.funnelback.com/12.0/query_operator.html but just need that final push.

Funnelback's default operator is and, and the mechanism for specifying or (in the underlying query syntax) is to wrap the or options in square brackets. What I think you want to end up with is the following query.
nematode M:[North South] N:["Category value 1" "Category value 2"]
It looks like you're trying to do that with the query broken down into CGI parameters though. Does...
query=nematode&meta_M=%5BNorth%20South%5D&meta_N=%5B%22Category%20value%201%22%20%22Category%20value%202%22%5D%20
# Note:
# meta_M decodes to [North South]
# meta_N decodes to ["Category value 1" "Category value 2"]
...cover what you need, or must each of the meta_M and meta_N values be in separate CGI parameters?

Related

Conditional Column: Order of Tests Matters?

Condition to Test Date
I am using Power Query to create a status column that checks the date against a specified date, like so:
However, this gives me the following error:
Expression.Error: We cannot convert the value null to type Logical.
Details:
Value=
Type=[Type]
The column does contain empty cells, which I want to report as "null" in the new column. I then tried the following logic, and it errors out as well:
Then I moved the null test to the top, and it finally works:
Why Does Order Matter?
Why does the third query produce the expected results but not the first one? This seems bizarre to me, so if there is something I am missing please let me know.
M is using lazy evaluation in the if statement. If the first statement is true, then it doesn't even bother evaluating the other conditions.
https://learn.microsoft.com/en-us/powerquery-m/m-spec-introduction
For computer language theorists: the formula language specified in
this document is a mostly pure, higher-order, dynamically typed,
partially lazy functional language.
Easy fix
On a step before your filter, choose "remove nulls" or "replace nulls with values"
using catch
If you want more flexibility, you can use a try + catch pair.
Step FirstTry is meant to; be your filter, then I added two ways to handle errors.
let
Source = Table.FromList(sample, Splitter.SplitByNothing(),
type table[Date = nullable date], null, ExtraValues.Error),
sample = {
#date(2020, 1, 1),
"text", null,
#date(2024, 1, 1)
},
filter = #date(2022, 1, 1),
FirstTry = Table.AddColumn(
Source , "Comparison", each filter > [Date], Logical.Type),
WithFallback = Table.AddColumn(FirstTry, "WithFallback",
each try
filter > [Date]
catch (e) => e[Message], type text),
WithPreservedDatatype = Table.AddColumn(WithFallback, "PreserveColumnType",
each try
filter > [Date]
catch (e) => null meta [ Reason = e[Message] ],
type logical)
in
WithPreservedDatatype
things to note
the query steps are "out of order", which is totally valid. ( above sample was referenced "before" its line )
Errors are propagated so an error on step4 could actually be step2. Just keep going up until you find it.
the schema says column [Date] is type date -- but it's actually type any.
What you need is to call Table.TransformColumnTypes to convert and assert datatypes
= Table.TransformColumnTypes( Source,{{"Date", type date}})
Now row 2 will correctly show an error, because text couldn't convert into a date
Better Understanding of NULLs
I was not understanding how Excel (or any other data tool) handles null values and how logical tests are performed on null values. This response on Reddit really helped clarify this in my mind:
https://www.reddit.com/r/excel/comments/xu37dr/comment/iqtmivn/?utm_source=share&utm_medium=web2x&context=3
In short, logical tests involving nulls do not behave like you would expect.
For a deeper dive into this, read this excellent post:
https://bengribaudo.com/blog/2018/09/13/4617/power-query-m-primer-part9-types-logical-null-binary
My Solution
Given this enlightened understanding of nulls and how they behave in logical tests, I now know that I must either:
Convert the null values to empty strings ("") before the query
Test first for nulls in the query
My choice is to test for nulls first within the query, like so:

How to quote/escape a field name in AQL for arangodb?

I cannot find where to quote a field name that has a space in it, for example when doing
FILTER s._key = a.`Supplier Id`
The above, sql-style quote doesn't work, neither does array access. What's the correct way?
Figured it out now, I got bitten by SQL and forgot that equality comparison is made with == in AQL. Then the array access worked, so the way to use field names with spaces is this:
FILTER s._key == a['Supplier Id']
If the field is without spaces but has some special characters, it works to use backtick instead of array access:
FILTER s._key == a.`ÅterförsäljareId`
Edit: Another option is to use bind variables:
FILTER s._key == a.#field
// Passing this to the API as bind variables:
{
"field": "Supplier Id"
}

Nested IF statement returning false

I have a nested if statement is returning "False" rather than the expected outcome.
Scenario
Table "High VoltageCables" has data in it that default to numeric but may contain characters: kVa
Table "Master" checks "High VoltageCables" data as blank or not blank, and returns "Failed Check 1","Passed Check 1". This works fine.
Table "Meta" then checks the results of "Master" and then tests "High VoltageCables" data for length between 1 and 6, regardless of whether record is numeric or string.
Formula
=IF(MASTER!H2="Passed Check 1",IF(LEN('High VoltageCables'!O2)>=1,IF(LEN('High VoltageCables'!O2<6),"Passed Check 2","Failed Check 2")))
This is partially succesful, as it returns "Passed Check 2" for the following sample data in the source table "High VoltageCables".
1 numeric, or
1kVa str, or
50000 numeric
However if a field in "High VoltageCables"is blank, the formula returns "FALSE" rather than "Failed Check 1"
I inherited this task, (and would have preferred to do the whole thing in Access using relatively simple queries) - and unfortunately I am new to nested If statements, so I am probably missing something basic...
NB the data in High VoltageCables must default to numeric for a further check to work.
The first and second IF's seem to be missing the else part. They should be added at the end between the ))) like ), else ), else )
Every IF statement consists of IF( condition, truepart, falsepart) if you have two nested ifs it will be something like IF( condition, IF( condition2, truepart2, falsepart2), falsepart)
Hope that makes it a little clearer
You do have an unaccounted for FALSE in the middle IF. Try bring the latter two conditions together.
=IF(Master!H2="Passed Check 1",IF(OR(LEN('High VoltageCables'!O2)={1,2,3,4,5}),"Passed Check 2","Failed Check 2"))
It's still a bit unclear on what to show or not show if Master!H2 does not equal "Passed Check 1".
I failed to construct the formula with a concluding "else" - "Failed Check 1"
Using jeeped's and Tom's suggestion and adding the final "else" part I have solved the problem:
=IF(MASTER!H2="Passed Check 1",IF(OR(LEN('High VoltageCables'!O2)={1,2,3,4,5}),"Passed Check 2","Failed Check 2"),"Failed Check 1")

Cognos query calculation - how to obtain a null/blank value?

I have a query calculation that should throw me either a value (if conditions are met) or a blank/null value.
The code is in the following form:
if([attribute] > 3)
then ('value')
else ('')
At the moment the only way I could find to obtain the result is the use of '' (i.e. an empty character string), but this a value as well, so when I subsequently count the number of distinct values in another query I struggle to get the correct number (the empty string should be removed from the count, if found).
I can get the result with the following code:
if (attribute='') in ([first_query].[attribute]))
then (count(distinct(attribute)-1)
else (count(distinct(attribute))
How to avoid the double calculation in all later queries involving the count of attribute?
I use this Cognos function:
nullif(1, 1)
I found out that this can be managed using the case when function:
case
when ([attribute] > 3)
then ('value')
end
The difference is that case when doesn't need to have all the possible options for Handling data, and if it founds a case that is not in the list it just returns a blank cell.
Perfect for what I needed (and not as well documented on the web as the opposite case, i.e. dealing with null cases that should be zero).

String Comparison with Elasticsearch Groovy Dynamic Script

I have an elasticsearch index that contains various member documents. Each member document contains a membership object, along with various fields associated with / describing individual membership. For example:
{membership:{'join_date':2015-01-01,'status':'A'}}
Membership status can be 'A' (active) or 'I' (inactive); both Unicode string values. I'm interested in providing a slight boost the score of documents that contain active membership status.
In my groovy script, along with other custom boosters on various numeric fields, I have added the following:
String status = doc['membership.status'].value;
float status_boost = 0.0;
if (status=='A') {status_boost = 2.0} else {status_boost=0.0};
return _score + status_boost
For some reason associated with how strings operate via groovy, the check (status=='A') does not work. I've attempted (status.toString()=='A'), (status.toString()=="A"), (status.equals('A')), plus a number of other variations.
How should I go about troubleshooting this (in a productive, efficient manner)? I don't have a stand-alone installation of groovy, but when I pull the response data in python the status is very much so either a Unicode 'A' or 'I' with no additional spacing or characters.
#VineetMohan is most likely right about the value being 'a' rather than 'A'.
You can check how the values are indexed by spitting them back out as script fields:
$ curl -XGET localhost:9200/test/_search -d '
{
"script_fields": {
"status": {
"script": "doc[\"membership.status\"].values"
}
}
}
'
From there, it should be an indication of what you're actually working with. More than likely based on the name and your usage, you will want to reindex (recreate) your data so that membership.status is mapped as a not_analyzed string. If done, then you won't need to worry about lowercasing of anything.
In the mean time, you can probably get by with:
return _score + (doc['membership.status'].value == 'a' ? 2 : 0)
As a big aside, you should not be using dynamic scripting. Use stored scripts in production to avoid security issues.

Resources