Query JSON column with array of objects MySQL - mysql

I have the following json array in my column:
[
{
"day": 1,
"requests": 23
},
{
"day": 2,
"requests": 5
},
{
"day": 2,
"requests": 9
}
]
and I want the row that has day 1. I already tried to do it with
SELECT * FROM api WHERE usages->'$[*].day' = JSON_ARRAY(1)
but it returns no results.

select usages->'$[*].day' from api shows that it's the JSON array [1,2,2].
where usages->'$[*].day' = JSON_ARRAY(1) is trying to match [1,2,2] with [1] which isn't true.
Instead, use JSON_CONTAINS to look for values within the array.
where json_contains(usages->'$[*].day', "1");

Related

Manipulating nested array of obects in RedisJSON

I have a JSON with nested array like below to be saved in Redis. I am using RedisJSON module to save the data as JSON.
customer:12345 : {
info : {
key1: val1,
key2: val2,
key3: val3
},
rides: [
{
rideid: xxx,
from: fromval,
to: toval,
date: dateofride,
distance: distanceval,
points: pointsval
},
{
rideid: yyy,
from: fromval,
to: toval,
date: dateofride,
distance: distanceval,
points: pointsval
},
...
]
}
I have a case where a new item can be added to the array or the existing one can be edited. I am using node-redis client with express.js. Express app receives only the data which is changed or added in rides array. If the item is already in the array, new data has to replace the existing array item (rideid is the key of each object), else it has to be added to the array. How do I achieve this?
Given the following JSON document
{
"info": {
"key1": "val1"
},
"rides": [{
"rideid": "xxx",
"points": 0
},
{
"rideid": "yyy",
"points": 10
}
]
}
Which is held by the key customer:12345 in RedisJSON with the following command
127.0.0.1:6379> JSON.SET customer:12345 . "{\"info\": {\"key1\": \"val1\",\"key2\": \"val2\",\"key3\": \"val3\"},\"rides\":[{\"rideid\": \"xxx\",\"points\": 0 },\t{\"rideid\": \"yyy\",\"points\": 10}]}"
You can update ride with rideid yyy by e.g. incrementing the score by 5 as follows
127.0.0.1:6379> JSON.NUMINCRBY customer:12345 "$.rides[?(#.rideid=='yyy')].points" 5
"[15]"
$.rides[?(#.rideid=='yyy')].points is a JSONPath expression (more here and here and also answered here)
To add a new ride
127.0.0.1:6379> JSON.ARRAPPEND customer:12345 $.rides "{\"rideid\": \"zzz\",\"points\": 5 }"
1) (integer) 3
All RedisJSON commands can be found here

Add string literal into JSONPath output

Can I add a string literal to a JSONPath selector?
{ "items": [
{ "x": 1 },
{ "x": 2 },
{ "x": 3 },
{ "x": 4 }]
}
$.items[:].x gives...
[
1,
2,
3,
4
]
For example, can I make it return...
[
{ 1 },
{ 2 },
{ 3 },
{ 4 }
]
I want to generate some code that adds items to a dictionary.
As discussed in the comments, this cannot be done using JSONPath (alone) since a path query returns only valid JSON and the target format is not valid. In general, JSONPath is not the right tool here, a JSON transformation using a library like Jolt would be more appropriate; but again, similar to XSLT transformations, we can only create valid output. So, as you already have found out, you would need to use string functions to mingle the code as needed. For instance, a regex substitution could do:
const regex = /(\d+),?/gm;
const str = `[
1,
2,
3,
4
]`;
const subst = `{ $1 },`;
// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
console.log('Substitution result: ', result);

Retrieving nested json information from a postgresql table - no current index

I'd like to retrieve nested json information from a jsonb field (sub_table) in a postgresql table (prices).
I'm able to retrieve the json using the command:
with jsontable as (
SELECT "sub_table"
FROM "prices"
WHERE "Scenario" = 'A' AND "data_type" = 'new'
)
SELECT * from jsontable
This returns a json table like this:
{
"0": {
"Name": "CompX",
"Price": 10,
"index": 1,
"Date": "2020-01-09T00:00:00.000Z"
},
"1": {
"Name": "CompY",
"Price": 20,
"index": 1,
"Date": "2020-01-09T00:00:00.000Z"
},
"2": {
"Name": "CompX",
"Price": 19,
"index": 2,
"Date": "2020-01-10T00:00:00.000Z"
}
}
I want to return all data relating to Name = "CompX" but can't get the query to work.
I've tried to follow the examples here, but can't work it out. Do I need to reindex in some way?
You can return extracted JSONB data row-wisely by using jsonb_each function with filtering out by (j.value -> 'Name')::text = '"CompX"' condition :
SELECT j.value
FROM prices p
CROSS JOIN jsonb_each(sub_table) AS j(e)
WHERE (j.value -> 'Name')::text = '"CompX"'
Demo

Extract values from a parsed json object using a function node or split & switch node in NODE.red

Was trying to extract values from a parsed json object using a function node or split & switch node, tried to many ways and nothing seems to work fro me.
the example below I would like to have 5 outputs for the text and numeric values.
here is my payload in json:
{
"applicationID": "1",
"applicationName": "test_ds18b20",
"deviceName": "arduino_uno",
"devEUI": "1234567890123456",
"rxInfo": [
{
"mac": "aa755a0048050130",
"rssi": -57,
"loRaSNR": 10,
"name": "raspberry_pi",
"latitude": 1.466860686785175,
"longitude": 2.019478797912605,
"altitude": 0
}
],
"txInfo": {
"frequency": 868100000,
"dataRate": {
"modulation": "LORA",
"bandwidth": 125,
"spreadFactor": 7
},
"adr": true,
"codeRate": "4/5"
},
"fCnt": 9,
"fPort": 1,
"data": "Z29vZGJ5ZQ==",
"object": {}
}
first i try with function node to extract "data", but it returns array like this:
0: ""data":"Z29vZGJ5ZQ==""
1: "Z29vZGJ5ZQ=="
i dont need array i need string
function:
var regexsearch = /\"data\":\"(.*?)\"/i;
var my = msg.payload.match(regexsearch);
msg.payload = my;
return msg;
but i need to get only this Z29vZGJ5ZQ==
than i try with split & switch nodes and gets the whole linelike this: ""data":"Z29vZGJ5ZQ==""
but i need to get only this Z29vZGJ5ZQ==
and here is my flow:
[{"id":"d46d38e2.27cc78","type":"inject","z":"ff592a31.cf21a8","name":"","topic":"","payload":"{\"applicationID\":\"1\",\"applicationName\":\"test_ds18b20\",\"deviceName\":\"arduino_uno\",\"devEUI\":\"1234567890123456\",\"rxInfo\":[{\"mac\":\"aa755a0048050130\",\"rssi\":-57,\"loRaSNR\":10,\"name\":\"raspberry_pi\",\"latitude\":48.466860686785175,\"longitude\":35.019478797912605,\"altitude\":0}],\"txInfo\":{\"frequency\":868100000,\"dataRate\":{\"modulation\":\"LORA\",\"bandwidth\":125,\"spreadFactor\":7},\"adr\":true,\"codeRate\":\"4/5\"},\"fCnt\":9,\"fPort\":1,\"data\":\"Z29vZGJ5ZQ==\",\"object\":{}}","payloadType":"json","repeat":"","crontab":"","once":false,"x":90,"y":160,"wires":[["1a34819e.743eee"]]},{"id":"105db6d9.0df1c9","type":"debug","z":"ff592a31.cf21a8","name":"","active":true,"console":"false","complete":"false","x":610,"y":100,"wires":[]},{"id":"1ac8a3e1.8f379c","type":"split","z":"ff592a31.cf21a8","name":"","splt":",","spltType":"str","arraySplt":"1","arraySpltType":"len","stream":false,"addname":"","x":250,"y":340,"wires":[["c10ec515.102d38"]]},{"id":"c10ec515.102d38","type":"switch","z":"ff592a31.cf21a8","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"\"data\":","vt":"str"},{"t":"cont","v":"\"latitude\":","vt":"str"}],"checkall":"true","outputs":2,"x":370,"y":340,"wires":[["105db6d9.0df1c9"],["6b2d5d19.7868e4"]]},{"id":"1a34819e.743eee","type":"json","z":"ff592a31.cf21a8","name":"","pretty":false,"x":115.55555555555556,"y":312.22222222222223,"wires":[["1ac8a3e1.8f379c","bae9fa5d.a9f238"]]},{"id":"bae9fa5d.a9f238","type":"function","z":"ff592a31.cf21a8","name":"match","func":"var regexsearch = /\\\"data\\\":\\\"(.*?)\\\"/i;\nvar my = msg.payload.match(regexsearch);\nmsg.payload = my;\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":160,"wires":[["105db6d9.0df1c9"]]},{"id":"6b2d5d19.7868e4","type":"debug","z":"ff592a31.cf21a8","name":"","active":true,"console":"false","complete":"false","x":610,"y":180,"wires":[]}]
Thanks for help

How to search nested JSON in MySQL

I am using MySQL 5.7+ with the native JSON data type. Sample data:
[
{
"code": 2,
"stores": [
{
"code": 100,
"quantity": 2
},
{
"code": 200,
"quantity": 3
}
]
},
{
"code": 4,
"stores": [
{
"code": 300,
"quantity": 4
},
{
"code": 400,
"quantity": 5
}
]
}
]
Question: how do I extract an array where code = 4?
The following (working) query has the position of the data I want to extract and the search criterion hardcoded:
SELECT JSON_EXTRACT(data_column, '$[0]')
FROM json_data_table
WHERE data_column->'$[1].code' = 4
I tried using a wildcard (data_column->'$[*].code' = 4) but I get no results in return.
SELECT row FROM
(
SELECT data_column->"[*]" as row
FROM json_data_table
WHERE 4 IN JSON_EXTRACT(data_column, '$[*].code')
)
WHERE row->".code" = 4
... though this would be much easier to work with if this wasn't an unindexed array of objects at the top level. You may want to consider some adjustments to the schema.
Note:
If you have multiple rows in your data, specifying "$[i]" will pick that row, not the aggregate of it. With your dataset, "$[1].code" will always evaluate to the value of code in that single row.
Essentially, you were saying:
$ json collection
[1] second object in the collection.
.code attribute labeled "code".
... since there will only ever be one match for that query, it will always eval to 4...
WHERE 4 = 4
Alternate data structure if possible
Since the entire purpose of "code" is as a key, make it the key.
[
"code2":{
"stores": [
{
"code": 100,
"quantity": 2
},
{
"code": 200,
"quantity": 3
}
]
},
"code4": {
"stores": [
{
"code": 300,
"quantity": 4
},
{
"code": 400,
"quantity": 5
}
]
}
]
Then, all it would require would be:
SELECT datacolumn->"[code4]" as code4
FROM json_data_table
This is what you are looking for.
SELECT data_column->'$[*]' FROM json_data_table where data_column->'$[*].code' like '%4%'.
The selected data will have [] around it when selecting from an array thus data_column->'$[*].code' = 4 is not possible.