Manipulating nested array of obects in RedisJSON - json

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

Related

Is it possible to add a key to a value that does not have a key in JSON?

I have a JSON without a key but just a value. Is it possible to add a key to it using React?
Here I have the and hanging without a key. How do I add a key to it, so that it's easier to read? I looked at JSON.Stringify and checked the replacer but it does not let me do it. delete also does not let me do it.
{
"sample": [
{
"id": "r-1",
"name": "sam"
},
"and",
{
"id": "r-2",
"name": "jerry"
}
]
}
You're confusing objects and arrays. The "key" with the string and as a value isn't a key. It's an array element (the value of the sample property is an array). It can't have a key unless you convert it from a string to an object, like the array elements before and after it, which are objects.
The structure of the array on the sample object property looks like this:
object | string | object
If you're ok changing your data from a string to an object, just replace the second array element (index 1) in the sample property with a new object:
const myObj = {
"sample": [{
"id": "r-1",
"name": "sam"
},
"and",
{
"id": "r-2",
"name": "jerry"
}
]
}
myObj.sample[1] = {
newKey: myObj.sample[1]
};
console.log(myObj);

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);

How to retrieve list item at index based on name from Json object in Python

E.g. Given the following JSON:
{
"success": true,
"message": "''",
"result": [
{
"buy": [
{
"quantity": 12.37,
"rate": 32.55412402
}
],
"sell": [
{
"quantity": 12.37,
"rate": 32.55412402
}
]
}
]
}
How would I go about retrieving the 'Buy' and 'Sell' to store into variables?
I can get the result via:
d = json.loads(string)
print(d['result'])
However I fail to see how to retrieve the buy object now. E.g. I've tried:
#print(d['result']['buy'])
#print(d['result'].buy)
#print(d['result'].indexOf('buy'))
All to no avail.
Try:
print(d['result'][0]['buy'])
should give you the buy object:
[{u'rate': 32.55412402, u'quantity': 12.37}]
If you inspect the type of d['result']:
print(type(d['result'])) # <type 'list'>
It's a list of length 1, so the [0] at the end of d['result'][0] will return that first and only item in the list which is the dictionary you are expecting that you can get by key ['buy'] as you did in your first try:
#print(d['result']['buy'])
there just need to index the list by [0]
#print(d['result'][0]['buy'])

Query JSON column with array of objects 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");

Storing a Key Value Array into a compact JSON string

I want to store an array of key value items, a common way to do this could be something like:
// the JSON data may store several data types, not just key value lists,
// but, must be able to identify some data as a key value list
// --> more "common" way to store a key value array
{
[
{"key": "slide0001.html", "value": "Looking Ahead"},
{"key": "slide0008.html", "value": "Forecast"},
{"key": "slide0021.html", "value": "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
],
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
But, when there is many pairs / items, the string length becomes prohibited,
and I want a compact way, this could be an example:
// --> (1) a "compact" way to store a key value array
{
[
{"slide0001.html", "Looking Ahead"},
{"slide0008.html", "Forecast"},
{"slide0021.html", "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
],
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
Additionally, I want a way to identify the data as a keyvalue array,
because, I may want to store other data in the same JSON file.
I have these examples:
// --> (2) a "compact" way to store a key value array
{
"keyvaluelist":
[
{"slide0001.html", "Looking Ahead"},
{"slide0008.html", "Forecast"},
{"slide0021.html", "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
],
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
// --> (3) a "compact" way to store a key value array
{
"mylist":
{
"type": "keyvaluearray",
"data":
[
{"slide0001.html", "Looking Ahead"},
{"slide0008.html", "Forecast"},
{"slide0021.html", "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
]
},
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
What do you thing, which one do you suggest, do you have another way ?
Thanks.
UPDATE 1: Remove invalid code. Javascript => JSON
UPDATE 2: Add non key value data
UPDATE 3: Replace "[" and "]" for "{" and "}" in each key value pair
So why don't you simply use a key-value literal?
var params = {
'slide0001.html': 'Looking Ahead',
'slide0002.html': 'Forecase',
...
};
return params['slide0001.html']; // returns: Looking Ahead
If the logic parsing this knows that {"key": "slide0001.html", "value": "Looking Ahead"} is a key/value pair, then you could transform it in an array and hold a few constants specifying which index maps to which key.
For example:
var data = ["slide0001.html", "Looking Ahead"];
var C_KEY = 0;
var C_VALUE = 1;
var value = data[C_VALUE];
So, now, your data can be:
[
["slide0001.html", "Looking Ahead"],
["slide0008.html", "Forecast"],
["slide0021.html", "Summary"]
]
If your parsing logic doesn't know ahead of time about the structure of the data, you can add some metadata to describe it. For example:
{ meta: { keys: [ "key", "value" ] },
data: [
["slide0001.html", "Looking Ahead"],
["slide0008.html", "Forecast"],
["slide0021.html", "Summary"]
]
}
... which would then be handled by the parser.
To me, this is the most "natural" way to structure such data in JSON, provided that all of the keys are strings.
{
"keyvaluelist": {
"slide0001.html": "Looking Ahead",
"slide0008.html": "Forecast",
"slide0021.html": "Summary"
},
"otherdata": {
"one": "1",
"two": "2",
"three": "3"
},
"anotherthing": "thing1",
"onelastthing": "thing2"
}
I read this as
a JSON object with four elements
element 1 is a map of key/value pairs named "keyvaluelist",
element 2 is a map of key/value pairs named "otherdata",
element 3 is a string named "anotherthing",
element 4 is a string named "onelastthing"
The first element or second element could alternatively be described as objects themselves, of course, with three elements each.
For use key/value pair in json use an object and don't use array
Find name/value in array is hard but in object is easy
Ex:
var exObj = {
"mainData": {
"slide0001.html": "Looking Ahead",
"slide0008.html": "Forecast",
"slide0021.html": "Summary",
// another THOUSANDS KEY VALUE PAIRS
// ...
},
"otherdata" : { "one": "1", "two": "2", "three": "3" }
};
var mainData = exObj.mainData;
// for use:
Object.keys(mainData).forEach(function(n,i){
var v = mainData[n];
console.log('name' + i + ': ' + n + ', value' + i + ': ' + v);
});
// and string length is minimum
console.log(JSON.stringify(exObj));
console.log(JSON.stringify(exObj).length);