How to cross reference a property in JMESPath or JSONPath? - normalization

I am trying to use jmespath for my querying my json and I am trying to access a property which is at a higher level.
Below is my JSON:
{
"properties": {
"DefaultVMTypeID": "RT",
"VM": {
"measurements": [
{
"vm": 45.62,
"vmString": "45.62",
"vmID": "RT",
"vmPathID": "osdu",
"vmTypeID": "RT",
"vmUnitOfMeasureID": "m"
},
{
"vm": 65,
"vmString": "65",
"vmID": "MT",
"vmPathID": "sample",
"vmTypeID": "MT",
"vmUnitOfMeasureID": "m"
},
{
"vm": 32,
"vmString": "32",
"vmID": "MT",
"vmPathID": "osduschemas",
"vmTypeID": "MT",
"vmUnitOfMeasureID": "m"
},
{
"vm": 95,
"vmString": "95",
"vmID": "MT",
"vmPathID": "schema",
"vmTypeID": "MT"
}
]
}
}
}
I want to get all the measurements whose vmId is equal to DefaultVMTypeID.
I tried below query:
[properties.DefaultVerticalmeasurementTypeID, properties.Verticalmeasurements.measurements[?VerticalmeasurementTypeID]] | map(&[1].VerticalmeasurementTypeID==#[0], #)
but when applying map to the array # refers to the element of the array and inside map there is no way I an access DefaultVMTypeID.
I have also tried transforming each element of an object.
Any leads would be appreciated.

I came across the TS translation on JMESPath library which has 2 enhancements.
Custom functions
Root Value Access
https://github.com/nanoporetech/jmespath-ts
This helped me solve my problem.
[properties.Verticalmeasurements.measurements][] | [?VerticalmeasurementID==$.properties.DefaultVerticalmeasurementTypeID]

You can actually use $ inside expressions to access the root of the JSON.
So the JSON Path
$.properties.VM.measurements[?(#.vmID==$.properties.DefaultVMTypeID)]
should work to get all the items in the measurements array that match.

Related

Mapbox GL JS: How can I use JavaScript with expressions to change layer layout?

I'm using Overpass to fetch OSM data and in Mapbox show the closest point of interest of a couple of 'categories'. I convert the OSM data to a GeoJSON layer and add it to Mapbox as a symbol layer with a marker image on each point in the data. The result looks like this:
I want to change the text displayed beneath each marker to something other than the variables I use to categorize the data. My first idea was to use a JS object like:
translate = {
'water': 'Waterway',
'city': 'City Center',
'school': 'Elementary School',
..etc
}
and then run each name through translate[venue_type]. This doesn't seem to work that easily though.
The marker is added as a layer like this:
map.loadImage(
'./img/map_marker3.png',
(error, image) => {
if (error) throw error;
if (!map.hasImage('custom-marker')) {
map.addImage('custom-marker', image);
}
map.addSource('venues',
{
'type': 'geojson',
'data': data
});
map.addLayer({
"id": "venues",
"type": "symbol",
"source": "venues",
'layout': {
'visibility': 'none',
'icon-image': 'custom-marker',
'icon-size': 1,
'icon-anchor': 'bottom',
'icon-allow-overlap': true,
// get the venue_type from the feature's venue_type property
'text-field': ['get','venue_type'],
'text-allow-overlap': true,
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 0.5],
'text-anchor': 'top'
}
});
callback();
});
with a GeoJson FeatureCollection of the following structure:
"type": "Feature",
"properties": {
"dist": 0.25566043226822727,
"index": 758,
"location": 21.218387011937942,
"name": "Östersjön",
"venue_type": "coastline"
},
"geometry": {
"type": "Point",
"coordinates": [
18.3434769,
59.4563257
]
}
The line responsible for setting the text underneath the marker is the following, which uses a Mapbox GL JS expression to fetch the field 'venue_type' from the properties of the GeoJSON object.
'text-field': ['get','venue_type']
I figured I could just do something like
'text-field': translate[['get','venue_type']]
but it gives the error:
Error: layers.venues.layout.text-field: 'undefined' value invalid. Use null instead.
at Object.ri [as emitValidationErrors]
text-field can take both a string, variable and a mapbox expression. But I'm not really sure if I can access the properties of the feature being added in any other way than the expression above.
Having looked into modifying the expression, it appears to be possible to use arithmetics and stuff, but I can't really find any example of mixing JavaScript into the expression.
Looking for some pointers here, should I go about it a different way? Or am I missing something?
First, this is a symbol layer, not a Marker.
You can't execute arbitrary JavaScript expressions within Mapbox GL expressions.
You can use a match expression, like this:
'text-field': [`match', ['get', 'venue_type'],
'water', 'Waterway',
'city', 'City Center',
'school', 'Elementary School',
''
]

Rego Validation Array Compare

I am new at Rego and I am trying to write a policy in order to check if there is a set of rules already created on certain Azure NSGs.
Input test:
{
"name": "<name>",
"id": "<id>",
"etag": "<etag>",
"type": "<resourcetype>",
"location": "<location>",
"properties":
{
"provisioningState": "Succeeded",
"resourceGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"securityRules":
[
{
"name": "<rule name>",
"id": "<id>",
"etag": "<etag",
"type": "<type>",
"properties":
{
"provisioningState": "Succeeded",
"description": "....",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "53",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Outbound",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes":
[
"10.0.0.1",
"10.0.0.2",
"10.0.0.3"
]
}
}
]
{
}
I wrote a custom function in order to check the values. Below is the code that I am testing in The Rego Playground
existRule(rule) = true
{
input.properties.securityRules[i].name == rule.name
input.properties.securityRules[i].properties.provisioningState == rule.provisioningState
input.properties.securityRules[i].properties.description == rule.description
input.properties.securityRules[i].properties.protocol == rule.protocol
input.properties.securityRules[i].properties.access == rule.access
input.properties.securityRules[i].properties.priority == rule.priority
input.properties.securityRules[i].properties.direction == rule.direction
}
rule = {
"name": "name",
"provisioningState": "Succeeded",
"description": "description",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "1",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Outbound",
"destinationAddressPrefix": "",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes": [
"10.0.0.1",
"10.0.0.2",
"10.0.0.3",
"10.0.0.4"
]
}
rules
{
existRule(rule)
}
which is working for the properties that I define above, however I am having an issue when trying to compare arrays, particularly in this example with destinationAddressPrefixes
I have tried the following:
test1 { input.properties.securityRules[i].properties.destinationAddressPrefixes == rule.destinationAddressPrefixes }
Always returns false
With the following line I can check one destination address from the input against a specific ip, however I can not achive a compare of all the address of the input against the ones of the rule that is defined in the example
onerule {input.properties.securityRules[i].properties.destinationAddressPrefixes[_] == "10.0.0.1"}
test2 {input.properties.securityRules[i].properties.destinationAddressPrefixes[_] == rule.destinationAddressPrefixes[j]}
test3 {input.properties.securityRules[i].properties.destinationAddressPrefixes[j] == rule.destinationAddressPrefixes[k]}
test2 and test3 always return true, even when there is a rule that is not in the input. I also tried and array difference
x := input.properties.securityRules[i].properties.destinationAddressPrefixes - rule.destinationAddressPrefixes
but I get the following error:
rego_type_error: minus: invalid argument(s) have: (any, array<string,
string, string, string, string, string, string, string, string,
string, string, string, string, string>, ???) want: (any<number,
set[any]>, any<number, set[any]>, any<number, set[any]>)
Do you know if it is feasible to achieve what I am looking for? Or is there a different way to make a look of the array and compare the values one by one?
What does rule3400.destinationAddressPrefixes look like?
If you want to compare for exact equality between two arrays, == should suffice.
If all elements are known to be unique and order doesn't matter (which seems to be the case in your example) you could convert the arrays to sets using a set comprehension. This makes it possible to subtract one set from another such as you tried to do with arrays directly.
to_set(arr) = {x | x := arr[_]}
input_prefixes := to_set(input.properties.securityRules[i].properties.destinationAddressPrefixes)
destination_prefixes := to_set(rule3400.destinationAddressPrefixes)
x := input_prefixes - destination_prefixes

How to get only matched data from nested class using query builder in elastic search?

I am trying to get only the matched data from nested array of elastic search class. but I am not able to get it..the whole nested array data is being returned as output.
this is my Query:-
QueryBuilders.nestedQuery("questions",
QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("questions.questionTypeId", quesTypeId)), ScoreMode.None)
.innerHit(new InnerHitBuilder());
I am using querybuilders to get data from nested class.Its working fine but not able to get only the matched data.
Request Body :
{
"questionTypeId" : "MCMC"
}
when questionTypeId = "MCMC"
this is the output i am getting..Here I want to exclude the output for which the questionTypeId = "SCMC".
output :
{
"id": "46",
"subjectId": 1,
"topicId": 1,
"subtopicId": 1,
"languageId": 1,
"difficultyId": 4,
"isConceptual": false,
"examCatId": 3,
"examId": 1,
"usedIn": 1,
"questions": [
{
"id": "46_31",
"pid": 31,
"questionId": "QID41336691",
"childId": "CID1",
"questionTypeId": "MCMC",
"instruction": "This is a single correct multiple choice question.",
"question": "Who holds the most english premier league titles?",
"solution": "Manchester United",
"status": 1000,
"questionTranslation": []
},
{
"id": "46_33",
"pid": 33,
"questionId": "QID41336677",
"childId": "CID1",
"questionTypeId": "SCMC",
"instruction": "This is a single correct multiple choice question.",
"question": "Who holds the most english premier league titles?",
"solution": "Manchester United",
"status": 1000,
"questionTranslation": []
}
]
}
As you have tagged this with spring-data-elasticsearch:
Support to return inner hits was recently added to version 4.1.M1 and so will be included in the next released version. Then in a SearchHit you will get the complete top level document, but in the innerHits property only the matching inner hits will be returned.

Return values for dimensions in timeseries query Druid

I have Druid timeseries query:
{
"queryType": "timeseries",
"dataSource": {
"type": "union",
"dataSources": [
"ds1",
"ds2"
]
},
"dimensions":["dim1"],
"aggregations": [
{
"name": "y1",
"type": "doubleMax",
"fieldName": "value1"
}
],
"granularity": {
"period": "PT10S",
"type": "period"
},
"postAggregations": [],
"intervals": "2017-06-09T13:05:46.000Z/2017-06-09T13:06:46.000Z"
}
And i want to return the values of the dimensions as well, not just for the aggregations like this:
{
"timestamp": "2017-06-09T13:05:40.000Z",
"result": {
"y1": 28.724306106567383
}
},
{
"timestamp": "2017-06-09T13:05:50.000Z",
"result": {
"y1": 28.724306106567383
}
},
How do I have to change the query? Thanks in advance!
If your requirement is to use dimension column in time series query that means you are using aggregated data with non aggregated column, this requirement leads to the use of topN or groupBy query.
groupBy query is probably one of the most powerful druid currently supports but it has poor performance as well, instead you can use topN query for your purpose.
Link for topN documentation and example can be found here:
http://druid.io/docs/latest/querying/topnquery.html
Is Timeseries() query is not supporting dimension?
I tried it in my project but it is not working.
here is Error:
TypeError: queryRep.dataSource(...).dimension is not a function
2|DSP-api | at dimensionData (/home/ec2-user/reports/dsp_reports/controllers/ReportController.js:228:22)
Let me know if anyone has a solution for this.
TY.

Message parameter doesn't allow html, so tried to use message_tags parameter in this format

Message parameter doesn't allow html, so tried to use message_tags parameter in this format, but with real values(format from here http://developers.facebook.com/blog/post/592/):
{
"19": [
{
"id": 101961456910,
"name": "Marmot",
"offset": 19,
"length": 6
}
],
"0": [
{
"id": 1207059,
"name": "Dhiren Patel",
"offset": 0,
"length": 12
}
]
}
and no result. Tried different values, there are no errors, but no result.
The message_tags parameter isn't one you can set via the API.
Did you find documentation suggesting otherwise? invalid parameters are for the most part silently ignored when you make a POST request

Resources