Recessively query Redis based on data type - redis

I am representing JSON objects in Redis by flattening the JSON path keys like so:
JSON object
{
"users": [
{
"name": "John Smith",
"address": {
"street": "12 Rainbow Avenue",
"country": "Fuzzyland"
}
}, {
"name": "Billy Bob",
"address": {
"street": "8 Rocky Lane",
"country": "Fraggleville"
}
}
]
}
Redis entries
users // SET [0, 1]
users:0 // SET [name, address]
users:0:name // STRING "John Smith"
users:0:address // SET [street, country]
users:0:address:street // STRING "12 Rainbow Avenue"
users:0:address:country // STRING "Fuzzyland"
users:1 // SET [name, address]
users:1:name // STRING "Billy Bob"
users:1:address // SET [street, country]
users:1:address:street // STRING "8 Rocky Lane"
users:1:address:country // STRING "Fraggleville"
As you can see, for properties that are arrays or object literals I am using a Redis SET to store the available keys.
It is easy enough for me to convert the JSON object to this structure using Node. However I am not experienced enough with Redis to write recursive queries that stitch together a complex result.
For example, say I want to get all the keys and values for users:1. How do I write a query that looks at the value of users:1 sees that it is a SET so uses the values from that as another set of query keys?

Related

SQL - Extract values from key value pairs to array

I'm querying some data (SQL, presto), the source data has an array struct that includes a name and ID. I need to have an array of the IDs.
The data looks like:
[ { "id": 123456789,
"name": "name 1" },
{ "id": 234567891,
"name": "name 2" }
]
and I need it to look like:
[123456789, 234567891]
Do you know how I can achieve this?
It's: MAP_KEYS(MAP_FROM_ENTRIES(column))

Karate: compare csv data with api response

I have a use case where I want to assert on a API response and compare it with the csv data.
Step1:
Csv file: *test.csv*
id,date,fullname,cost,country,code
1,02-03-2002,user1,$200,Canada,CAN
2, 04-05-2016,user2,$1500,United States, USA
I read the csv file and store it in a variable
def var1 = read(test.csv)
So now, var1 is a list of jsons based on my csv
var1 = [
{
"id":1,
"date":"02-03-2002",
"fullname": "user1",
"cost": "$200",
"country": "Canada",
"code": "CAN"
},
{
"id":2,
"date":"04-05-2016",
"fullname": "user2",
"cost": "$1500",
"country": "United States",
"code": "USA"
}
]
Step2:
I hit my api and get a response
Given url "https://dummyurl.com
Given path "/userdetails"
When method get
Then status 200
* def apiResponse = response
Step 3:
My api returns a list response which is:
{
"id":1,
"date":"02-03-2002",
"fullname": "user1",
"cost": "$200",
"country": {
"name": "Canada",
"code": "CAN"
}
},
{
"id":2,
"date":"05-04-2012",
"fullname": "user2",
"cost": "$1500",
"country": {
"name": "United States",
"code": "USA"
}
},
...and more 100 records..
]
Step 4:
So there are two assertions now which I wanted to perform
Get the count of csvresponse and apiresponse and compare which I did using the .length operator
Secondly, I want to confirm if each csv records are matching with each api response.
And if possible in my case id key from csv and apiresponse is primary key, so if I can iterate on id and match the api response for any discrepancy.
Let me know if this is readable for you and if I was able to explain my use case.
Thanks for your earlier response.
Please read up on the match contains syntax, that's all you need: https://github.com/intuit/karate#match-contains
So this one line should be enough:
* match var1 contains response
Also look at this answer in case the new contains deep helps: https://stackoverflow.com/a/63103746/143475
Try to avoid iterating, it is not needed for most API tests. But you can certainly do it. Look at these answers:
https://stackoverflow.com/a/62567262/143475
Also read this - because I suspect you are trying to over-complicate your tests. Please don't. Write tests where your are 100% sure of the "shape" of the response as far as possible: https://stackoverflow.com/a/54126724/143475
And please please read the docs. It is worth it.

How to pass json parameters in jmeter?

In jmeter, I want to pass dynamic parameters. For simple json its easy to put ${value1} but if json structure is complex like array or with multiple values then what is the proper method to pass parameter dynamically. Please refer below json.
Below is json with parameter :
{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}
=======
Now I have used below method to send parameter through csv config file.
Is there any other simple method to pass parameter through variables in Jmeter for complex json (5-6 level with array data) ?
CSV DATA config is the best to parameterize your test data.
If you want to customize the way you want to pick values from CSV you can use BeanShell /JSR223 sampler
here is one article that shows how to pick random values from CSV data config.

Figure out different values to send partial update to server

From a form submission I receive two objects: the original values and the dirty values. I like to figure out how to create a diff to send to the server using the following rules:
id field of the root object should always be included
all changed primitive values should be included
all nested changes should be included as well.
if a nested value other than id changed, it should include id as well.
Original values:
{
"id":10,
"name": "tkvw"
"locale": "nl",
"address":{
"id":2,
"street": "Somewhere",
"zipcode": "8965",
},
"subscriptions":[8,9,10],
"category":{
"id":6
},
}
Example expected diff objects:
1) User changes field name to "Foo"
{
"id":10,
"name":"foo"
}
2) User changes field street on address node and category
{
"id":10,
"address":{
"id": 2,
"street":"Changed"
},
"category":{
"id":5
}
}
I do understand the basics of functional programming, but I just need a hint in the right direction (some meta code maybe).
Take a look at JSON Patch (rfc6902), JSON Patch is a format for describing changes to a JSON document. For example:
[
{ "op": "replace", "path": "/baz", "value": "boo" },
{ "op": "add", "path": "/hello", "value": ["world"] },
{ "op": "remove", "path": "/foo"}
]
You generate a patch by comparing to JS objects/arrays, and then you can apply the patch to the original object (on the server side for example) to reflect changes.
You can create a patch using the fast-json-patch lib.
const obj1 = {"id":10,"name":"tkvw","locale":"nl","address":{"id":2,"street":"Somewhere","zipcode":"8965"},"subscriptions":[8,9,10],"category":{"id":6}};
const obj2 = {"id":10,"name":"cats","locale":"nl","address":{"id":2,"street":"Somewhere","zipcode":"8965"},"subscriptions":[8,9,10,11],"category":{"id":7}};
const delta = jsonpatch.compare(obj1, obj2);
console.log('delta:\n', delta);
const doc = jsonpatch.applyPatch(obj1, delta).newDocument;
console.log('patched obj1:\n', doc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fast-json-patch/2.0.6/fast-json-patch.min.js"></script>

How to map two related JSONs using RestKit?

I have two JSONs, which are looking like:
{
"749": {
"email": "myMail#me.com",
"firstname": "Mr",
"lastname": "Smith"
}
}
and
[
{
"entity_id": "1",
"city": "myCity",
"country_id": "UA",
"region": null,
"postcode": "001",
"telephone": "+38000000001",
"fax": null,
"street": [
"myStrit ",
"12"
],
"is_default_billing": 1,
"is_default_shipping": 0
},
{
"entity_id": "2",
"city": "myCity",
"country_id": "UA",
"region": null,
"postcode": "001",
"telephone": "+3800000002",
"fax": null,
"street": [
"myStrit2",
"33"
],
"is_default_billing": 0,
"is_default_shipping": 1
}
]
Path for getting first JSON is mySite/customers, and for the second is mySite/customers/:userId/addresses.
where userId is unnamed attribute from first JSON (749 in my example).
I am new in RestKit and I can't really figure out, how to map it by one request...
PS: I get these JSONs from Magento rest api.
You say nothing about what you're trying to map into, but.
For the first JSON, you need to use addAttributeMappingFromKeyOfRepresentationToAttribute on the mapping to extract the 749 value and use it as a key at the same time.
For the second JSON there doesn't appear to be any connection to the first so you need to try mapping that and come back with specific issues. See this page for guidance.
RestKit expects each object to be described by a dictionary which can be processed by the mapper. Your service does not return an array of objects, though, rather a dictionary of dictionaries, which RestKit cannot correctly interpret as a collection of objects it can map individually. Of course, the problem would disappear if your service could return an array of dictionaries instead.
Fortunately, there is a way to transform the dictionary of dictionaries you receive into an array of dictionaries right before the mapper is called. This is achieved by setting a conversion block via -[RKObjectRequestOperation setWillMapDeserializedResponseBlock:].
The block receives the result of the initial parsing (here the dictionary of dictionaries), which you can easily turn into an array of dictionaries by calling -[NSDictionary allValues]:
RKManagedObjectStore *managedObjectStore = ...;
RKResponseDescriptor *responseDescriptor = ...;
NSURLRequest *request = ...;
RKManagedObjectRequestOperation *managedObjectRequestOperation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[responseDescriptor]];
managedObjectRequestOperation.managedObjectContext = managedObjectStore.mainQueueManagedObjectContext;
[managedObjectRequestOperation setWillMapDeserializedResponseBlock:^id(id deserializedResponseBody) {
return [deserializedResponseBody allValues];
}];
[[NSOperationQueue currentQueue] addOperation:managedObjectRequestOperation];