Can we make pack_all consider only non-null & non-empty columns - azure-data-explorer

pack_all() function considers all the input columns while making a dynamic object. Is it possible to somehow force it to consider only non-empty & non-null columns? If not, is there any workaround to apply filter on top of the resulting dynamic value?

There is no flavor of pack_all that will do it, but as an alternative, you can combine mv-apply and mv-expand operators to achieve this. Here is an example (adapted from the docs):
datatable(SourceNumber:string,TargetNumber:string,CharsCount:long)
[
'555-555-1234','555-555-1212',46,
'555-555-1234','555-555-1213',50,
'555-555-1212','',int(null)
]
| extend values =pack_all()
| mv-apply removeProperties = values on
(
mv-expand kind = array values
| where isempty(values[1])
| summarize propsToRemove = make_set(values[0])
)
| extend values = bag_remove_keys(values, propsToRemove)
| project-away propsToRemove

It should be added as a new answer, that pack_all() did in the meantime get a new option to exclude null/empty values
pack_all([ignore_null_empty])
ignore_null_empty: An optional bool indicating whether to
ignore null/empty columns and exclude them from the resulting property
bag. Default: false.
https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/packallfunction

Related

Use query to populate an extend in KQL?

I have a JSON property bag being received as an update to configuration. I would like to retrieve the existing latest property bag from the table, manipulate it to remove the keys that are being updated using the bag_remove_keys and bag_merge operators.
This is being used in an update policy, so I have the new property bag in an extend from the input data, I need to perform a new extend to retrieve the current latest property set existing in the table.
Something similar to the below:
rawhsimessages
//Get #RecType
| extend ParsedMessage = parse_json(Message)
| extend Objects = ParsedMessage["ExportedConfig"]["Objects"]
| parse Objects with "[" Objects "]"
| extend Properties = parse_json(Objects)
| extend RecType = Properties["#RecType"]
| where RecType == "CHANGE"
| extend latestconfig = XXXX(GeoSCADAConfigurationTest | where Id == Properties["Id"] | summarize arg_max(ConfigTime, Properties)
| project-away Message, ParsedMessage, Objects
Can I replace the XXXX with anything that will allow me to do this?
If not, is there a better approach I can take?

Summarizing amount of times options are selected true/false in a concatenated string

I'm pretty new to KQL and I'm having a difficult time with it (I don't have a background in stats, and I'm not very good at SQL either). I have telemetry data coming in from Microsoft AppCenter that I want to parse out into some charts but I'm trying to first figure out how to split a concatenated string that is essentially a dictionary that has two possible values: true and false. I want to count the number of each, so every key would have 2 values (true/false) which would also each have a numerical count value.
The input string I'm trying to get this data from is of the format Remove Splash/Main Menu Branding=True;Disable Aim Assist=False - unique items are split by ; and each pair is split by =. I am trying to figure out which options my users are using this way. The example string here would be split into:
Remove Splash/Main Menu Branding = True (count 1)
Disable Aim Assist = False (count 1).
If a new item came in that was Remove Splash/Main Menu Branding=True;Disable Aim Assist=True the summarized data would be
Remove Splash/Main Menu Branding = True (count 2)
Disable Aim Assist = False (count 1).
Disable Aim Assist = True (count 1).
So far I've got a query that selects a single item, but I don't know how to count this across multiple rows:
customEvents
| where timestamp > ago(7d)
| where name == "Installed a mod"
| extend Properties = todynamic(tostring(customDimensions.Properties))
| where isnotnull(Properties.["Alternate Options Selected"])
| extend OptionsStr = Properties.["Alternate Options Selected"] //The example string in above
| extend ModName = Properties.["Mod name"]
| where ModName startswith "SP Controller Support" //want to filter only to one mod's options
| extend optionsSplit = split(OptionsStr, ";")
| summarize any(optionsSplit)
I'm not sure how to make counts of it in a dictionary though. If anyone has any suggestions or tips or examples on something like this, I would really appreciate it, thanks.
Here you go:
let MyTable = datatable(Flags:string) [
"Remove Splash/Main Menu Branding=True;Disable Aim Assist=False",
"Remove Splash/Main Menu Branding=True;Disable Aim Assist=True"
];
MyTable
| extend Flags = split(Flags, ";")
| mv-expand Flag = Flags to typeof(string)
| summarize Count = count() by Flag
The output of this is:
| Flag | Count |
|---------------------------------------|-------|
| Remove Splash/Main Menu Branding=True | 2 |
| Disable Aim Assist=False | 1 |
| Disable Aim Assist=True | 1 |
Explanation:
First you split every input string (that contains multiple flags) into substrings, so that each will only have a single flag - you achieve this by using split.
Now your new Flags column has a list of strings (each one containing a single flag), and you want to create a record with every string, so you use the mv-expand operator
Lastly, you want to count how many times every key=value pair appears, and you do it with summarize count() by Flag
In case you want to see one record (in the output) per Key, then you can use the following query instead:
let MyTable = datatable(Flags:string) [
"Remove Splash/Main Menu Branding=True;Disable Aim Assist=False",
"Remove Splash/Main Menu Branding=True;Disable Aim Assist=True"
];
MyTable
| extend Flags = split(Flags, ";")
| mv-expand Flag = Flags to typeof(string)
| parse Flag with Key "=" Value
| project Key, Value
| evaluate pivot(Value, count(Value))
Its output is:
| Key | False | True |
|----------------------------------|-------|------|
| Remove Splash/Main Menu Branding | 0 | 2 |
| Disable Aim Assist | 1 | 1 |
You wrote that you're new to KQL, so you might find the following free Pluralsight courses interesting:
How to start with Microsoft Azure Data Explorer
Basic KQL
Azure Data Explorer – Advanced KQL
P.S. In the future please provide sample input in datatable format (if you're using Kusto Explorer, just select the relevant query results, right-click on the selection, and click Copy as datatable() literal), and also the expected output in a table format, so that it will be easier to understand what you want to achieve.

DynamoDB boto3 : How to query if a key has some value

I'm writing a python code to query a table on dynamo DB. Along with other conditions I'd also like to get rows where there exists some value for the key I'm specifying.
KeyConditionExpression = Key('Status').eq('Done') & Key('Name').begins_with('A') & Key('Error').exists()
In the code above, I'd like to display rows where the column "Error" has some value be it anything.
but the last condition is throwing an error.
AttributeError: 'Key' object has no attribute 'exists'.
How can modify the code to incorporate the third query?
Assuming that your “Error” key is neither your partition key and nor sort key as you must specify the partition key name and value as an equality condition always. Also, for the sort key you can use one of the undermentioned comparison operators.
a = b — true if the attribute a is equal to the value b
a < b — true if a is less than b
a <= b — true if a is less than or equal to b
a > b — true if a is greater than b
a >= b — true if a is greater than or equal to b
a BETWEEN b AND c — true if a is greater than or equal to b, and less than or equal to c.
begins_with (a, substr)— true if the value of attribute a begins with a particular substring.
Now coming back to your issue, if you are using Query operation, then you can definitely use QueryFilter to check if some non-null value exists for key “Error”. The official documentation defines QueryFilter as :
In a Query operation, QueryFilter is a condition that evaluates the query results after the items are read and returns only the desired values.
The following comparison operators are available for QueryFilter:
EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN
Please refer to the undermentioned link to get more idea about the QueryFilter and FilterExpression
AWS Official Documentation Link : https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/LegacyConditionalParameters.QueryFilter.html

Replacing empty string column with null in Kusto

How do I replace empty (non null) column of string datatype with null value?
So say the following query returns non zero recordset:-
mytable | where mycol == ""
Now these are the rows with mycol containing empty strings. I want to replace these with nulls. Now, from what I have read in the kusto documentation we have datatype specific null literals such as int(null),datetime(null),guid(null) etc. But there is no string(null). The closest to string is guid, but when I use it in the following manner, I get an error:-
mytable | where mycol == "" | extend test = translate(mycol,guid(null))
The error:-
translate(): argument #0 must be string literal
So what is the way out then?
Update:-
datatable(n:int,s:string)
[
10,"hello",
10,"",
11,"world",
11,"",
12,""
]
| summarize myset=make_set(s) by n
If you execute this, you can see that empty strings are being considered as part of sets. I don't want this, no such empty strings should be part of my array. But at the same time I don't want to lose value of n, and this is exactly what will happen if I if I use isnotempty function. So in the following example, you can see that the row where n=12 is not returned, there is no need to skip n=12, one could always get an empty array:-
datatable(n:int,s:string)
[
10,"hello",
10,"",
11,"world",
11,"",
12,""
]
| where isnotempty(s)
| summarize myset=make_set(s) by n
There's currently no support for null values for the string datatype: https://learn.microsoft.com/en-us/azure/kusto/query/scalar-data-types/null-values
I'm pretty certain that in itself, that shouldn't block you from reaching your end goal, but that goal isn't currently clear.
[update based on your update:]
datatable(n:int,s:string)
[
10,"hello",
10,"",
11,"world",
11,"",
12,""
]
| summarize make_set(todynamic(s)) by n

Substitute variable name in a dynamic json property

I would like to use the variable settingName for the dynamic json property. How can i accomplish that?
let settingName = 'LaunchNext';
DSEvents
| where Timestamp > ago(1d) and Data contains (settingName)
| summarize count() by tostring(parsejson(tostring(Data.Settings)).LaunchNext.value)
I want to substitute the variable instead of the actual property
parsejson(tostring(Data.Settings)).LaunchNext.value
Enclosing the variable in [] worked for me
tostring(parsejson(tostring(Data.Settings)).[settingName].value)

Resources