Get the path of a jsonata match - jsonata

I'm using jsonata to query a json file that I have. I have a query that returns an array of results with the value from each match. What I also want to know is what is the exact path to my match.
Example:
Suppose I had the following JSON
"files": [
{
"name": "file_1",
"type": "txt"
},
{
"name": "file_2",
"type": "csv"
},
{
"name": "file_3",
"type": "txt"
}
]
}
and I had the following query:
files[type="txt"].name
I would like to know both the value of my query results and the path of all hits. E.g:
[
{value: "file_1", path: "files[0].name"},
{value: "file_3", path: "files[2].name"}
]
Is this something that is possible?

I do not think JSONata has such feature. But there could be another way to achieve what you are looking for.
If you are interested in the index value, there is a built-in operator is JSONata - Positonal Variable Binding operator.
And if you're interested in knowing the parent of a given search, you could use the Parent operator.

Here's a practical example that builds on #anindya-dey's answer. Maybe it's all you need, maybe not.
Input json
{
"files": [
{
"name": "file_1",
"type": "txt"
},
{
"name": "file_2",
"type": "csv"
},
{
"name": "file_3",
"type": "txt"
}
]
}
Jsonata expression
files#$i[type="txt"].{
'value': name,
'path': 'files[' & $i & '].name'
}
Result
[
{
"value": "file_1",
"path": "files[0].name"
},
{
"value": "file_3",
"path": "files[2].name"
}
]

Related

How can i form the property in compose to return int(0) if condition is true and not return anything if condition is false?

How can i form this expression to return int value of 0 if true and don't return the property if false? warehouse event is an array and the property is inside a compose.
Expression:
if(contains(variables('WareHouseEvent'), 'OB_2910'), int(0), <not
return anything)
An alternative to the first answer is to always add and then remove it after the fact.
This is an example you can copy into your own tenant for testing.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose_JSON_Object": {
"inputs": {
"AnotherProperty": "Another Value",
"TestProperty": "#variables('Data')"
},
"runAfter": {
"Initialize_Integer": [
"Succeeded"
]
},
"type": "Compose"
},
"Initialize_Integer": {
"inputs": {
"variables": [
{
"name": "Data",
"type": "integer",
"value": 0
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"New_JSON_Object": {
"inputs": {
"variables": [
{
"name": "New Object",
"type": "object",
"value": "#if(equals(variables('Data'), 1), removeProperty(outputs('Compose_JSON_Object'), 'TestProperty'), outputs('Compose_JSON_Object'))"
}
]
},
"runAfter": {
"Compose_JSON_Object": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"conditions": [],
"inputs": {},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
I have an integer variable at the top which stores a value of either 1 or 0.
Then in my compose, I add that value to a property in the compose statement.
Then beneath that, I set a new variable with the (potentially) updated object using an expression to determine if the added property should be removed or not.
You'd just need to adjust the condition portion of the IF statement with your expression.
if(equals(variables('Data'), 1), removeProperty(outputs('Compose_JSON_Object'), 'TestProperty'), outputs('Compose_JSON_Object'))
The property will be removed depending on the value of the Data variable.
Removed
Retained
One of the workarounds is that you can use Condition connector when if the mentioned condition satisfies it executes true block else it executes false. From there you can use the same Compose content.
Here is the screenshot of the logic app -
output :-

How to use JSONpath to extract specific values

I'm using JSONpath to try and find data with an array of JSON objects but I'm struggling to get to the information I want. The array contains many objects similar to below where there are values for RecID throughout. If I use $..RecID I get them all when I only want the first Key.RecID of each object (with a value 1338438 in this example). Is there a way to only extract the top level Key.RecID value?
BTW I'm trying to do this in jMeter and I'm assuming JSONpath is the best way to do what I want but if there is a better way I'd be happy to hear about it.
Thanks in advance
[{
"Key": {
"RecID": 1338438
},
"Users": [{
"FullName": "Miss Burns",
"Users": {
"Key": {
"Name": "Burns",
"RecID": 1317474
}
}
},
{
"FullName": "Mrs Fisher",
"Users": {
"Key": {
"Name": "Fisher",
"RecID": 1317904
}
}
}
],
"User": {
"FullName": "Mrs Fisher",
"Key": {
"Name": "Fisher",
"RecID": 1317904
}
},
"Organisation": {
"Key": {
"RecID": 1313881
}
}
}]

NiFi Jolt Specification for array input

I have the following input in Nifi Jolt Specification processor:
[
{
"values": [
{
"id": "paramA",
"value": 1
}
]
},
{
"values": [
{
"id": "paramB",
"value": 3
}
]
}
]
Expected output:
[
{
"id": "paramA",
"value": 1
},
{
"id": "paramB",
"value": 2
}
]
Can you explain how I have to do?
thanks in advance
You want to reach the objects of the values array which are nested within seperate object signs ({}). A "*" notation is needed in order to cross them over per each individual values array, and then use another "*" notation for indexes of those arrays while choosing "" as the counterpart values in order to grab nothing but the sub-objects such as
[
{
"operation": "shift",
"spec": {
"*": {
"values": {
"*": ""
}
}
}
}
]

Incorrectly selected data in the query

Only articles that contain the EmailMarketing tag are needed.
I'm probably doing the wrong search on the tag, since it's an array of values, not a single object, but I don't know how to do it right, I'm just learning graphql. Any help would be appreciated
query:
query {
enArticles {
title
previewText
tags(where: {name: "EmailMarketing"}){
name
}
}
}
result:
{
"data": {
"enArticles": [
{
"title": "title1",
"previewText": "previewText1",
"tags": [
{
"name": "EmailMarketing"
},
{
"name": "Personalization"
},
{
"name": "Advertising_campaign"
}
]
},
{
"title": "title2",
"previewText": "previewText2",
"tags": [
{
"name": "Marketing_strategy"
},
{
"name": "Marketing"
},
{
"name": "Marketing_campaign"
}
]
},
{
"title": "article 12",
"previewText": "article12",
"tags": []
}
]
}
}
I believe you first need to have coded an equality operator within your GraphQL schema. There's a good explanation of that here.
Once you add an equality operator - say, for example _eq - you can use it something like this:
query {
enArticles {
title
previewText
tags(where: {name: {_eq: "EmailMarketing"}}){
name
}
}
}
Specifically, you would need to create a filter and resolver.
The example here may help.

elasticsearch: unable to set geo_shape value using XContentBuilder

I have following mapping in elastic search. I am able to PUT documents using Sense plugin but unable to do so using XContentBuilder to set the geo_shape field value. I am getting following error:
error:
[106]: index [streets], type [street], id [{dc872755-f307-4c5e-93f6-bba9c95791c7}], message [MapperParsingException[failed to parse [shape]]; nested: ElasticsearchParseException[shape must be an object consisting of type and coordinates];]
mapping:
PUT /streets
{
"mappings": {
"street": {
"properties": {
"id": {
"type": "string"
},
"shape": {
"type": "geo_shape",
"tree": "quadtree"
}
}
}
}
}
code:
val bulkRequest:BulkRequestBuilder = esClient.prepareBulk()
//inloop
xb = jsonBuilder().startObject()
xb.field("id", guid)
xb.field("shape", jsonString) // removing this line creates the index OK but without the geo_shape
xb.endObject()
bulkRequest.add(esClient.prepareIndex("streets", "street", guid).setSource(xb))
//end loop
val bulkResponse:BulkResponse = bulkRequest.execute().actionGet()
if(bulkResponse.hasFailures){
println(bulkResponse.buildFailureMessage())
}
jsonString:
{
"id": "{98b8fd8d-074c-4349-a83b-6e892bf2d0ef}",
"shape": {
"type": "LineString",
"coordinates": [
[-70.81866815832467, 43.12187109162505],
[-70.83054813653018, 43.15917412985851],
[-70.81320737213957, 43.23522269547419],
[-70.90108590067649, 43.28102004268419]
],
"crs": {
"type": "name",
"properties": {
"name": "EPSG:4326"
}
}
}
}
Appreciate any feedback?
Thanks
It might be a bit late for you, but this could help someone facing a similar issue even nowadays.
Following your index mapping for the document streets, we have these properties: id and shape.
In your error message, it's described that:
shape must be an object consisting of type and coordinates
So for your concrete case, the crs array is just not accepted (don't know exactly why you can't add extra parameters).
This is an example for how to add a document into the streets index using CURL:
curl -X POST "localhost:9200/streets/_doc?pretty" -H 'Content-Type: application/json' -d '
{
"id": 123,
"shape": {
"type": "Polygon",
"coordinates": [
[
[
32.85444259643555,
39.928694653732364
],
[
32.847232818603516,
39.9257985682691
],
[
32.837791442871094,
39.91947941109337
],
[
32.837276458740234,
39.91579296675271
],
[
32.85392761230469,
39.913423004886894
],
[
32.86937713623047,
39.91329133793421
],
[
32.88036346435547,
39.91539797880347
],
[
32.85444259643555,
39.928694653732364
]
]
]
}
}'
If you need to add a LineString, instead of a Polygon, just change the 'type' attribute from the 'shape'.
I hope this helps people having to add documents with shapes into an ElasticSearch database.

Resources