Replace empty value in dictionary Kusto - azure-data-explorer

I have this data:
let data = datatable(Timestamp:datetime, Name:string, Value:int)
[
datetime(2022-02-18 10:00:00 AM), "Floor 1", 100,
];
let mydict = dynamic(
{
"Id":"1",
"Product": ""
}
);
data
| extend messageMetaData = mydict
| project Timestamp, Name, Value, messageMetaData = replace_string(tostring(messageMetaData), "", "Wheat")
What I am trying to achieve here is to replace the empty value in messageMetaData by a string. When running this code it is giving me the exact same result/
Expected result:

print mydict = dynamic({"Id":"1", "Product": ""})
| extend messageMetaData = replace_string(tostring(mydict), '""', '"Wheat"')
mydict
messageMetaData
{"Id":"1","Product":""}
{"Id":"1","Product":"Wheat"}
Fiddle

Related

jq: how to add double quotes for string values

given this JSON:
{
"stringKey": "this is a string",
"numberKey": 1234,
"jsonKey": [
{"numberKey": 1, "stringKey": "0x" }
]
}
and this jq expression
to_entries|map("export let " + .key + " = " + (.value | tostring)) | .[]
I get this:
export let stringKey = this is a string
export let numberKey = 1234
export let jsonKey = [{"numberKey":1,"stringKey":"0x"}]
however I want this (note double quotes around this is a string):
export let stringKey = "this is a string"
export let numberKey = 1234
export let jsonKey = [{"numberKey":1,"stringKey":"0x"}]
jqplay snippet can be found https://jqplay.org/s/MYdILy4Xfw3
any help? thanks!
Use tojson, not tostring. It does exactly what you need for all data types.
to_entries|map("export let " + .key + " = " + (.value | tojson)) | .[]
Check it online.
To get a JSON-encoded output, use tojson instead of tostring:
jq -r 'to_entries[] | "export let " + .key + " = " + (.value | tojson)'
export let stringKey = "this is a string"
export let numberKey = 1234
export let jsonKey = [{"numberKey":1,"stringKey":"0x"}]
Demo
With the same effect, you can also use the #json syntax and provide the value through string interpolation:
jq -r 'to_entries[] | "export let " + .key + #json " = \(.value)"'
export let stringKey = "this is a string"
export let numberKey = 1234
export let jsonKey = [{"numberKey":1,"stringKey":"0x"}]
Demo
Note: For simplicity, I have also turned map(…) | .[] into .[] | ….

jq query to pull values from json file to create a listing

Given this input small sample:
{
"_format_version": "1.1",
"_workspace": "test",
"services": [
{
"connect_timeout": 60000,
"host": "host-name-test.com",
"name": "name-of-service",
"path": "/test/oauthpass",
"port": 777,
"protocol": "http",
"read_timeout": 1000,
"retries": 1,
"write_timeout": 1000,
"routes": [
{
"hosts": [
"Google.com"
],
"name": "com.testing.active.oauth",
"methods": [
"POST"
],
"paths": [
"/vendors/otest/pass/?$"
],
"path_handling": "v8",
"preserve_host": false,
"protocols": [
"https"
],
"regex_priority": 0,
"strip_path": true,
"https_redirect_status_code": 426,
"request_buffering": true,
"response_buffering": true
}
]
}
}
trying to get a listing from the data pulling certain values like the listing below:
host-name-test.com, Google.com, POST, HTTPS
the command that I have working so far is
cat /tmp/petecar.json | jq -r ' .services[] | .routes[] | ( .hosts[] + "/" + .paths[]) ' | more
but I can't access the values under services, please provide some sample on how to get the values
routes has an array value and as such cannot be concatenated with a string. You can use join to turn that array into a single string:
jq -r '.services[] | .host + " " + (.routes[].hosts | join(","))'
Output:
host-name-test.com Google.com
Alternatively, using string interpolation) which will automatically serialize any values into their string representation:
jq -r '.services[] | "\(.host) \(.routes[].hosts)"'
Output:
host-name-test.com ["Google.com"]
join and string interpolation can be combined, giving you the identical output of the first command:
jq -r '.services[] | "\(.host) \(.routes[].hosts|join(","))"'

KQL - Convert Dynamic Array of Key Value to Key Value dictionary

I have a cell of a table-column that is a dynamic. This was ingested from .Net as a Dictionary, but in Kusto it looks like an array of objects, that has a property key and value:
[
{"key":"ProjectId","value":"1234"},
{"key":"ProjectName","value":"Albatros"},
{"key":"User","value":"Bond"}
]
I want to convert the contents of the cell in my Kusto query to the following dynamic:
{
"ProjectId": "1234",
"ProjectName": "Albatros",
"User": "Bond"
}
I cant figure out how to write the expression, that converts it form the array into the new dynamic format.
Can anyone point me in the right direction?
you can use a combination of mv-apply and make_bag():
print d = dynamic([
{"key": "value"},
{"ProjectId": "1234"},
{"ProjectName": "Albatros"},
{"User": "Bond"}
])
| mv-apply d on (
summarize result = make_bag(d)
)
result
{ "key": "value", "ProjectId": "1234", "ProjectName": "Albatros", "User": "Bond"}
UPDATE based on your change to the original question:
print d = dynamic([
{"key":"ProjectId","value":"1234"},
{"key":"ProjectName","value":"Albatros"},
{"key":"User","value":"Bond"}
])
| mv-apply d on (
summarize result = make_bag(pack(tostring(d.key), d.value))
)
result
{ "ProjectId": "1234", "ProjectName": "Albatros", "User": "Bond"}

Flask restx api model not showing model data

I have a model as follows:
class Menu(db.Model):
itemId = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(255),index=True)
price = db.Column(db.Numeric)
description = db.Column(db.String(255),index=True)
image = db.Column(db.LargeBinary)
restaurantId = db.Column(db.Integer, db.ForeignKey('restaurants.id'))
createdOn = db.Column(db.DateTime,server_default=db.func.now())
status = db.Column(db.Integer,server_default="1")
orders = db.relationship('Orders', backref='menu', lazy='dynamic')
def __repr__(self):
return '<Menu of restaurant id {}>'.format(self.restaurantId)
And I have the following api model corresponding to it:
menu_model = api.model('Menu',
{'itemId':fields.Integer(),
'name':fields.String(),
'price':fields.Float(),
'description':fields.String(),
'restaurantId':fields.Integer(),
'createdOn:':fields.DateTime(),
'status':fields.Integer()})
The problem is that even though the createdOn values are correctly generated on DB side, the response shows the createdOn field as null. What could be the reason?
"menu":
{
"itemId": 1,
"name": "Menu item",
"price": 30.0,
"description": "Menu item description",
"restaurantId": 1,
"createdOn:": null,
"status": 1
}
this will accept the desired output. The first parameter is a label, not part of the json
menus = api.model(
"menu_item",
{
'itemId':fields.Integer(),
'name':fields.String(),
'price':fields.Float(),
'description':fields.String(),
'restaurantId':fields.Integer(),
'createdOn:':fields.DateTime(),
'status':fields.Integer()
},
)
menu_model = api.model(
"Menu",
{
"menu": Nested(menus),
},
)

Interaction between {} and select

Here's my test data:
[
{
"id": "id-1",
"tags": {
"key": "name",
"value": "name-1"
}
},
{
"id": "id-2"
}
]
I'm trying to simplify the output, to show the 'name' field if present, and always show the id. For example, this script almost works:
~ $ cat testdata | jq '.[] | {id, name: .tags.value}'
{
"id": "id-1",
"name": "name-1"
}
{
"id": "id-2",
"name": null
}
When I try to add in a guard against .keys not existing and filter for the section of 'keys' I care about, here's what happens:
~ $ cat testdata | jq '.[] | {id, name: (select(.tags.key == "name") | .tags.value)}'
{
"id": "id-1",
"name": "name-1"
}
I assume {} is somehow ending up with a zero-length array instead of 'null'. What should I be using instead of |? What am I misunderstanding?
I ended up solving the problem using: [POSSIBLY_MATCHED_EXPRESSION][0], in this case:
cat testdata | jq '.[] | {id, name: ([select(.tags.key == "name") | .tags.value][0])}'
If I'm understanding correctly, if you wanted to include a name only if it existed, I'd do this:
map({id} + with_entries(select(.key == "tags") | .value))
Otherwise if you don't mind null names:
map({id, name: with_entries(select(.key == "tags") | .value) | .name})
Here's a more general solution if you have other "tags" so it's not hardcoded to only accept name values.
This assumes that any object value is actually a key/value pair.
map(with_entries(if .value | type == "object" then .value else . end))
Or if tags is the only dynamic property:
map(with_entries(if .key == "tags" then .value else . end))
If the goal is to produce:
{"id":"id-1","name":"name-1"}
{"id":"id-2"}
then the following three expressions are essentially equivalent solutions:
.[] | if .tags.key == "name" then {id, name: .tags.value} else {id} end
.[] | {id} + (if .tags.key == "name" then {name: .tags.value} else {} end)
.[] | (select(.tags.key == "name") | {id, name: .tags.value}) // {id}
You could just add
| if .name == null then del(.name) else . end
to the end of your filter to get rid of the .name key when its value is null.
With your test data, the following
.[]
| {id, name:.tags.value }
| if .name == null then del(.name) else . end
produces
{
"id": "id-1",
"name": "name-1"
}
{
"id": "id-2"
}

Resources