i want to assert values between 2 json files.
Here is the code i tried, it works fine but i have more than 300 values to test.
Instead of having 300 lines is there a better way to do it with a loop :
file1.json content is:
[
{
"Name": "Pierre",
"Address": 1,
"City": "Paris",
"Country": "FRA",
"Code": "2020-01-01T00:00:00",
"Position": " 7000,00 $ "
},
{
"Name": "Pierre",
"Address": 2,
"City": "Paris",
"Country": "USA",
"Code": "2020-01-01T00:00:00",
"Position": " 9000,00 $ "
},
{
"Name": "Pierre",
"Address": 3,
"City": "Paris",
"Country": "GER",
"Code": "2020-01-01T00:00:00",
"Position": " 2000,00 $ "
}
]
file2.json content is:
{"value": {
"data": {"number1": [
[
{
"Name": "Pierre",
"Address": 1,
"City": "Paris",
"Country": "FRA",
"Code": "2020-01-01T00:00:00",
"Position": " 7000,00 $ "
},
{
"Name": "Paul",
"Address": 2,
"City": "Paris",
"Country": "USA",
"Code": "2020-01-01T00:00:00",
"Position": " 9000,00 $ "
},
{
"Name": "Pierre",
"Address": 3,
"City": "Paris",
"Country": "GER",
"Code": "2020-01-01T00:00:00",
"Position": " 2000,00 $ "
},
"Name": "Luc",
"Address": 6,
"City": "Pekin",
"Country": "CHN",
"Code": "2020-01-01T00:00:00",
"Position": " 800,00 $ "
},
]
]
}
i want to assert each value of file1 with file2.
For exemple:
JsonSlurper jsonSlurper1 = new JsonSlurper()
File file1Actual = new File('c:/temp/file1.json')
def actualJson = jsonSlurper1.parse(file1Actual)
JsonSlurper jsonSlurper2 = new JsonSlurper()
File file2Expected = new File('c:/temp/file2.json')
def expectedJson = jsonSlurper2.parse(file2Expected)
assert actualJson.value.data.number1.Name[0] == expectedJson.Name[0]
assert actualJson.value.data.number1.Name[1] == expectedJson.Name[1]
assert actualJson.value.data.number1.Name[2] == expectedJson.Name[2]
Thank you for any suggestions
Assuming you are actually coding in Groovy (not Java) as your code example suggests, something like the following should do it:
/* ... read in the Json files as outlined in the question ... */
actualJson.value.data.number1.size.times {
// Just to demonstrate that 'it' takes on values 0, 1, 2, 3, 4 etc.
println "assert number ${it}"
assert actualJson.value.data.number1.Name[it] == expectedJson.Name[it]
}
However this is a very 'groovyesque' way of doing it. If you want something a tad closer what a Java developer would write, you would maybe do:
/* read in Jsons, then: */
// Let's assign the list to a var for better readability
def actualList = actualJson.value.data.number1
// Bonus points for asserting that both lists are of equal size
// assert actualList.size == expectedJson.size
// If this does not hold then
def smaller = Math.min(actualList.size, expectedJson.size)
// a classic for-loop.
for (int i = 0; i < smaller; i++) {
println "assert number ${i}"
assert actualList[i].Name == expectedJson[i].Name
}
Related
I have an array of documents, that have more or less same structure. But I need find fields that present in all documents. Somethink like:
{
"name": "Jow",
"salary": 7000,
"age": 25,
"city": "Mumbai"
},
{
"name": "Mike",
"backname": "Brown",
"sex": "male",
"city": "Minks",
"age": 30
},
{
"name": "Piter",
"hobby": "footbol",
"age": 25,
"location": "USA"
},
{
"name": "Maria",
"age": 22,
"city": "Paris"
},
All docs have name and age. How to find them with ArangoDB?
You could do the following:
Retrieve the attribute names of each document
Get the intersection of those attributes
i.e.
LET attrs = (FOR item IN test RETURN ATTRIBUTES(item, true))
RETURN APPLY("INTERSECTION", attrs)
APPLY is necessary so each list of attributes in attrs can be passed as a separate parameter to INTERSECTION.
Documentation:
ATTRIBUTES: https://www.arangodb.com/docs/stable/aql/functions-document.html#attributes
INTERSECTION: https://www.arangodb.com/docs/stable/aql/functions-array.html#intersection
APPLY: https://www.arangodb.com/docs/stable/aql/functions-miscellaneous.html#apply
DATA to be search through:
{
"epicUserHandle": "HaaZeeY",
"stats": {
"p2": {
"trnRating": {
"label": "TRN Rating",
"field": "TRNRating",
"category": "Rating",
"valueInt": 1193,
"value": "1193",
"rank": 3210238,
"percentile": 56.0,
"displayValue": "1,193"
},
"top1": {
"label": "Wins",
"field": "Top1",
"category": "Tops",
"valueInt": 46,
"value": "46",
"rank": 15163718,
"percentile": 0.8,
"displayValue": "46"
},
My code:
url = "https://api.fortnitetracker.com/v1/profile/{}/{}".format(platform,
username)
headers = {'TRN-Api-Key' : 'MY API KEY'}
r = requests.get(url, headers=headers)
#p2 = Solo
#p10 = Duo
#p9 = Squad
tempory_dict = {}
result = r.json()['stats']['p2']['top1']
for r in result:
#WHAT DO I PUT HERE
tempory_dict['Wins'] = #VALUE
print(tempory_dict['Wins'])
What do I need to do here? I want it to find the "value" and save that in the tempory_dict['Wins']. I'm new to requests and not sure how to iterate through it all to find value.
Thanks.
You are almost there actually, having:
result = r.json()['stats']['p2']['top1'], you actually assign
{
"label": "Wins",
"field": "Top1",
"category": "Tops",
"valueInt": 46,
"value": "46",
"rank": 15163718,
"percentile": 0.8,
"displayValue": "46"
}
to result variable, so all you need to do is just go one step further and assign:
tempory_dict['Wins'] = result['value']
I am trying to get to grips with map/reduce queries when using PouchDB/CouchDB.
I have a lot of documents in my database but I need to create a design that queries the documents and gives me all of the unique team names as a key and then tells me
a) how many unique wards are within each team
b) the total number of jobs per team (across all wards)
The structure of my data is:
{
"_id": "0448071807c0f37f53e06aab54034a42",
"_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
"team": "Team A",
"ward": "Ward A",
"date": "2017-03-30",
"person": "Alice",
"bed": "Bed 001",
"jobs": [1,2,3,4]
}
{
"_id": "0448071807c0f37f53e06aab54034a42",
"_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
"team": "Team A",
"ward": "Ward B",
"date": "2017-03-30",
"person": "Bob",
"bed": "Bed 001",
"jobs": [1,2]
}
{
"_id": "0448071807c0f37f53e06aab54034a42",
"_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
"team": "Team A",
"ward": "Ward C",
"date": "2017-03-30",
"person": "Charles",
"bed": "Bed 001",
"jobs": [9,5]
}
{
"_id": "0448071807c0f37f53e06aab54034a42",
"_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
"team": "Team B",
"ward": "Ward 00",
"date": "2017-03-30",
"person": "David",
"bed": "Bed 001",
"jobs": [1]
}
The output I would expect would be like this:
Team A
- 3 unique wards
- 8 jobs
Team B
- 1 unique ward
- 1 job
e.g.
{
"key": "Team A",
"value": {
"wards": 3,
"jobs": 8
}
}
{
"key": "Team B",
"value": {
"wards": 1,
"jobs": 1
}
}
My map is currently:
{
"all": {
"map": "function(doc) { emit(doc.team, doc) }"
}
}
It is the reduce where my struggle comes in.
EDIT
I have taken the suggestions used on CouchDB View equivalent of SUM & GROUP BY but this only goes half way towards my challenge.
If I use:
{
"all": {
"map": "function(doc) { emit([doc.team, doc.ward], 1) }",
"reduce": "function(keys, values) { return sum(values); }"
}
}
And then go to http://my-ip:5984/wardround_jobs/_design/teams/_view/all?group_level=1 then I see the unique teams (good) and the number of occurrences (also great) but I am unsure how I extend the reduce function to include the total number of jobs.
First, you have to emit the jobs length (has the number of jobs) :
function (doc) {
emit([doc.team,doc.ward],doc.jobs.length);
}
Then, you need a reduce function like this :
function (keys, values, rereduce) {
var stats = {uniq:0,jobs:0};
if (rereduce) {
for(var i=0;i<values.length;i++){
stats.uniq += values[i].uniq;
stats.jobs += values[i].jobs;
}
return stats;
}
stats.uniq = values.length;
stats.jobs = sum(values);
return stats;
}
For the first iteration, we return an object (stats) with the number of wards perm team (uniq) and the number of jobs (we sum the jobs length of every team/ward.
Then, for the rereduce, we simply aggregate the object`s values.
I have an object stored in arangodb which has additional inner objects, my current use case requires that I update just one of the elements.
Store Object
{
"status": "Active",
"physicalCode": "99999",
"postalCode": "999999",
"tradingCurrency": "USD",
"taxRate": "14",
"priceVatInclusive": "No",
"type": "eCommerce",
"name": "John and Sons inc",
"description": "John and Sons inc",
"createdDate": "2015-05-25T11:04:14+0200",
"modifiedDate": "2015-05-25T11:04:14+0200",
"physicalAddress": "Corner moon and space 9 station",
"postalAddress": "PO Box 44757553",
"physicalCountry": "Mars Sector 9",
"postalCountry": "Mars Sector 9",
"createdBy": "john.doe",
"modifiedBy": "john.doe",
"users": [
{
"id": "577458630580",
"username": "john.doe"
}
],
"products": [
{
"sellingPrice": "95.00",
"inStock": "10",
"name": "School Shirt Green",
"code": "SKITO2939999995",
"warehouseId": "723468998682"
},
{
"sellingPrice": "95.00",
"inStock": "5",
"name": "School Shirt Red",
"code": "SKITO245454949495",
"warehouseId": "723468998682"
},
{
"sellingPrice": "95.00",
"inStock": "10",
"discount": "5%",
"name": "School Shirt Blue",
"code": "SKITO293949495",
"warehouseId": "723468998682"
}
]
}
I want to change just one of the products stock value
{
"sellingPrice": "95.00",
"inStock": "10",
"discount": "5%",
"name": "School Shirt Blue",
"code": "SKITO293949495",
"warehouseId": "723468998682"
}
Like update store product stock less 1 where store id = x, something to this effect
FOR store IN stores
FILTER store._key == "837108415472"
FOR product IN store.products
FILTER product.code == "SKITO293949495"
UPDATE product WITH { inStock: (product.inStock - 1) } IN store.products
Apart from the above possibly it makes sense to store product as a separate document in collection store_products. I believe in NOSQL that is the best approach to reduce document size.
Found answer
here arangodb-aql-update-single-object-in-embedded-array and there
arangodb-aql-update-for-internal-field-of-object
I however believe it is best to maintain separate documents and rather use joins when retrieving. Updates easily
I'm attempting a fairly basic task in arangodb, using the SUM() aggregate function.
Here is a working query which returns the right data (though not yet aggregated):
FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : g[*].m[*].items }
This returns the following results:
[
{
"memberId": "40289",
"amount": [
[
{
"amount": 50,
"description": "some description"
}
],
[
{
"amount": 50,
"description": "some description"
},
{
"amount": 500,
"description": "some description"
},
{
"amount": 0,
"description": "some description"
}
],
[
{
"amount": 0,
"description": "some description"
},
]
]
}
]
I am using Collect to group the results because a given memberId may have multiple'RegMem' objects. As you can see from the query/results, each object has a list of smaller objects called 'items', with each item having an amount and a description.
I want to SUM() the amounts by member. However, adjusting the query like this does not work:
FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : SUM(g[*].m[*].items[*].amount) }
It returns 0 because it apparently can't find a field in the expanded items list called amount.
Looking at the results I can sort of understand why: the results are being returned such that items is actually a list, of lists of objects with amount/description. But I don't understand how to reference or expand the un-named list correctly to return the amount field values for the SUM() function.
Ideally the query should return the memberId and total amount, one row per member such that I can remove the filter and execute for all members.
Many thanks in advance if you can help!
Martin
PS I've worked through the AQL tutorial on the arangodb website and checked out the manual but what would really help me is loads more example queries to look through. If anyone knows of a resource like that or wants to share some of their own, 'much obliged. Cheers!
Edited: Misread the question the first time. The first one can be seen in theedit history, as it also contains some hints:
I replicated your data by creating some documents in this format (and some with only one item):
{
"memberId": "40289",
"items": [
{
"amount": 50,
"description": "some description"
},
{
"amount": 500,
"description": "some description"
}
]
}
Based on some of those types of documents, your non-summarized query should indeed be looking like this:
FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : g[*].m[*].items }
The data returned:
[
{
"memberId": "40289",
"amount": [
[
{
"amount": 50,
"description": "some description"
},
{
"amount": 0,
"description": "some description"
}
],
[
{
"amount": 50,
"description": "some description"
},
{
"amount": 0,
"description": "some description"
}
],
[
{
"amount": 50,
"description": "some description"
}
],
[
{
"amount": 50,
"description": "some description"
},
{
"amount": 500,
"description": "some description"
}
],
[
{
"amount": 0,
"description": "some description"
}
],
[
{
"amount": 50,
"description": "some description"
},
{
"amount": 500,
"description": "some description"
}
]
]
}
]
Based on the non summarized version, you need to loop through the items of the groups that have been generated by the collect function and do your SUM() there.
In order to be able to SUM the items you must FLATTEN() them into a single list, before summarizing them.
FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : SUM(
FLATTEN(
(
FOR r in g[*].m[*].items
RETURN r[*].amount
)
)
)
}
This results in:
[
{
"memberId": "40289",
"amount": 1250
}
]