How to sort hash in ruby recursively - json

I have a huge hash/json in below format. Sample is given.
How we can sort this result hash based on the "total" key in descending order?
Nb: The last level nested node will not have have response and total keys. They will have metrics as keys.
result = {
"account_id_1": {
"total": 1000,
"response": {
"location_1": {
"total": 300,
"response": {
"service_1": { "metrics": { "cost": 100} },
"service_2": { "metrics": { "cost": 100 } },
"service_3": { "metrics": { "cost": 100 } },
}
},
"location_2": {
"total": 500,
"response": {
"service_1": { "metrics": { "cost": 300 } },
"service_2": { "metrics": { "cost": 150 } },
"service_3": { "metrics": { "cost": 50 } },
}
},
"location_3": {
"total": 200,
"response": {
"service_1": { "metrics": { "cost": 75 } },
"service_2": { "metrics": { "cost": 75 } },
"service_3": { "metrics": { "cost": 50 } },
}
}
}
},
"account_id_2": {
"total": 2000,
"response": {
"location_1": {
"total": 300,
"response": {
"service_1": { "metrics": { "cost": 100 } },
"service_2": { "metrics": { "cost": 100 } },
"service_3": { "metrics": { "cost": 100 } },
}
},
"location_2": {
"total": 500,
"response": {
"service_1": { "metrics": { "cost": 300 } },
"service_2": { "metrics": { "cost": 150 } },
"service_3": { "metrics": { "cost": 50 } },
}
},
"location_3": {
"total": 1200,
"response": {
"service_1": { "metrics": { "cost": 1075 } },
"service_2": { "metrics": { "cost": 75 } },
"service_3": { "metrics": { "cost": 50 } },
}
}
}
}
}
Expected result:
result = {
"account_id_2": {
"total": 2000,
"response": {
"location_3": {
"total": 1200,
"response": {
"service_1": { "metrics": { "cost": 1075 } },
"service_2": { "metrics": { "cost": 75 } },
"service_3": { "metrics": { "cost": 50 } },
}
},
"location_2": {
"total": 500,
"response": {
"service_1": { "metrics": { "cost": 300 } },
"service_2": { "metrics": { "cost": 150 } },
"service_3": { "metrics": { "cost": 50 } },
}
},
"location_1": {
"total": 300,
"response": {
"service_1": { "metrics": { "cost": 100 } },
"service_2": { "metrics": { "cost": 100 } },
"service_3": { "metrics": { "cost": 100 } },
}
}
}
},
"account_id_1": {
"total": 1000,
"response": {
"location_2": {
"total": 500,
"response": {
"service_1": { "metrics": { "cost": 300 } },
"service_2": { "metrics": { "cost": 150 } },
"service_3": { "metrics": { "cost": 50 } },
}
},
"location_1": {
"total": 300,
"response": {
"service_1": { "metrics": { "cost": 100} },
"service_2": { "metrics": { "cost": 100 } },
"service_3": { "metrics": { "cost": 100 } },
}
},
"location_3": {
"total": 200,
"response": {
"service_1": { "metrics": { "cost": 75 } },
"service_2": { "metrics": { "cost": 75 } },
"service_3": { "metrics": { "cost": 50 } },
}
}
}
}
}

Personally I would create a class to handle the custom sorting so that we can implement our own <=> (Spaceship Operator)
Something like: (Working Example: https://replit.com/#engineersmnky/ThankfulAutomaticRam#main.rb)
class AccountLocaleMetricSorter
include Comparable
def self.sort(h)
h.map do |name,values|
new(name: name, data: values)
end.sort.reduce({}) {|m,o| m.merge(o.to_h)}
end
attr_reader :name, :data, :o_data
def initialize(name: , data: )
#name = name
#o_data = data
#data = parse_response(data)
end
def to_h
return {name.to_sym => o_data} unless o_data.key?(:total)
{name.to_sym => {
total: o_data[:total],
response: data.to_h
}
}
end
def <=>(other)
if o_data.key?(:total) && o_data.key?(:total)
other.o_data[:total] <=> o_data[:total]
elsif other.o_data.key?(:metrics) && o_data.key?(:metrics)
other.o_data.dig(:metrics,:cost) <=> o_data.dig(:metrics,:cost)
else
0
end
end
private
def parse_response(response)
return response unless response.key?(:response)
self.class.sort(response[:response])
end
end
Usage as:
pp AccountLocaleMetricSorter.sort(result)
Output:
{:account_id_2=>
{:total=>2000,
:response=>
{:location_3=>
{:total=>1200,
:response=>
{:service_1=>{:metrics=>{:cost=>1075}},
:service_2=>{:metrics=>{:cost=>75}},
:service_3=>{:metrics=>{:cost=>50}}}},
:location_2=>
{:total=>500,
:response=>
{:service_1=>{:metrics=>{:cost=>300}},
:service_2=>{:metrics=>{:cost=>150}},
:service_3=>{:metrics=>{:cost=>50}}}},
:location_1=>
{:total=>300,
:response=>
{:service_1=>{:metrics=>{:cost=>100}},
:service_2=>{:metrics=>{:cost=>100}},
:service_3=>{:metrics=>{:cost=>100}}}}}},
:account_id_1=>
{:total=>1000,
:response=>
{:location_2=>
{:total=>500,
:response=>
{:service_3=>{:metrics=>{:cost=>300}},
:service_2=>{:metrics=>{:cost=>150}},
:service_1=>{:metrics=>{:cost=>50}}}},
:location_1=>
{:total=>300,
:response=>
{:service_1=>{:metrics=>{:cost=>100}},
:service_2=>{:metrics=>{:cost=>100}},
:service_3=>{:metrics=>{:cost=>100}}}},
:location_3=>
{:total=>200,
:response=>
{:service_1=>{:metrics=>{:cost=>75}},
:service_2=>{:metrics=>{:cost=>75}},
:service_3=>{:metrics=>{:cost=>50}}}}}}}

Let's first simplify your example.
result = {
"account_id_1": {
"total": 1000,
"response": {
"location_1": { "total": 300, "response": 1 },
"location_2": { "total": 500, "response": 2 },
"location_3": { "total": 200, "response": 3 }
}
},
"account_id_2": {
"total": 2000,
"response": {
"location_1": { "total": 300, "response": 1 },
"location_2": { "total": 500, "response": 2 },
"location_3": { "total": 1200, "response": 3 }
}
}
}
In your example,
result[:account_id_1][:response][:location_1][:response]
#=> { "service_1": { "metrics": { "cost": 100} },
# "service_2": { "metrics": { "cost": 100 } },
# "service_3": { "metrics": { "cost": 100 } } }
This value, and others like it, will remain unchanged, so I've replaced it with a placeholder, an arbitrary integer:
result[:account_id_1][:response][:location_1][:response]
#=> 1
result[:account_id_1][:response][:location_2][:response]
#=> 2
and so on.
I found it useful to create a helper method:
def sort_by_total_desc(h)
h.sort_by { |_,g| -g[:total] }.to_h
end
The desired hash can then be computed as follows.
sort_by_total_desc(result.transform_values do |v|
v.merge(response: sort_by_total_desc(v[:response]))
end)
#=> {:account_id_2=>{
# :total=>2000,
# :response=>{
# :location_3=>{:total=>1200, :response=>3},
# :location_2=>{:total=>500, :response=>2},
# :location_1=>{:total=>300, :response=>1}
# }
# },
# :account_id_1=>{
# :total=>1000,
# :response=>{
# :location_2=>{:total=>500, :response=>2},
# :location_1=>{:total=>300, :response=>1},
# :location_3=>{:total=>200, :response=>3}
# }
# }
# }
Regarding the helper method, here is an example.
h = { "location_1": { "total": 300, "response": 1 },
"location_2": { "total": 500, "response": 2 },
"location_3": { "total": 200, "response": 3 } }
sort_by_total_desc(h)
#=> {:location_2=>{:total=>500, :response=>2},
# :location_1=>{:total=>300, :response=>1},
# :location_3=>{:total=>200, :response=>3}}
which requires two steps:
a = h.sort_by { |_,g| -g[:total] }
#=> [[:location_2, {:total=>500, :response=>2}],
# [:location_1, {:total=>300, :response=>1}],
# [:location_3, {:total=>200, :response=>3}]]
a.to_h
#=> as above
The main method has two main steps. First perform the "inner" sorting.
h = result.transform_values do |v|
v.merge(response: sort_by_total_desc(v[:response]))
end
#=> {:account_id_1=>{
# :total=>1000,
# :response=>{
# :location_2=>{:total=>500, :response=>2},
# :location_1=>{:total=>300, :response=>1},
# :location_3=>{:total=>200, :response=>3}
# }
# },
# :account_id_2=>{
# :total=>2000,
# :response=>{
# :location_3=>{:total=>1200, :response=>3},
# :location_2=>{:total=>500, :response=>2},
# :location_1=>{:total=>300, :response=>1}
# }
# }
# }
Then do the "outer" sorting to return the desired result:
sort_by_total_desc(h)
#=> as above
See Enumerable#sort_by, Hash#transform_values and Hash#merge.

Related

This pack is missing one or more dependencies - JSON behavior pack code is not working. -Minecraft bedrock

I have been trying to get this Minecraft bedrock behavior pack working for a while now. I used a guide, so I could learn how to make behavior packs but no matter how many times I look back through it, I still can't figure out what the problem is. The referenced texture pack works fine, but the behavior does not work.
Minecraft bedrock v1.17.34.
in file : development_resource_packs > RP cow
This is the manifest.json for the resource pack.
// development_resource_packs > RP cow > manifest.json
{
"format_version": 2,
"header": {
"description": "My First Add-On!",
"name": "Hello WorldRP",
"uuid":"9b0e1712-ba26-4d3c-be42-2b6c4d160305",
"version": [1, 0, 0],
"min_engine_version": [1, 16, 0]
},
"modules": [
{
"description": "My First Add-On!",
"type": "resources",
"uuid": "f2ccdadd-c9ac-4d53-8daf-a3520537ea7e",
"version": [1, 0, 0]
}
]
}
// development_behavior_packs > HelloWorldBP > manifest.json
{
"format_version": 2,
"header": {
"description": "My First Add-On!",
"name": "Hello WorldBP",
"uuid":"c3fac618-a713-4516-b1eb-1b9c7c75b1db",
"version": [1, 0, 0],
"min_engine_version": [1, 16, 0]
},
"modules":
[
{
"description": "My First Add-On!",
"type": "data",
"uuid": "e34d68ac-72f2-44c2-a514-b83673f919c0",
"version": [1, 0, 0]
}
],
"dependencies": [
{
"uuid":"9b0e1712-ba26-4d3c-be42-2b6c4d160305",
"version":[1,0,0]
}
]
}
// HelloWorldBP > entities > cow.json
{
"format_version": "1.16.0",
"minecraft:entity": {
"description": {
"identifier": "minecraft:cow",
"is_spawnable": true,
"is_summonable": true,
"is_experimental": false
},
"component_groups": {
"minecraft:cow_baby": {
"minecraft:is_baby": {
},
"minecraft:scale": {
"value":0.5
},
"minecraft:ageable": {
"duration": 1200,
"feed_items": "wheat",
"grow_up": {
"event": "minecraft:ageable_grow_up",
"target": "self"
}
},
"minecraft:behavior.follow_parent": {
"priority": 6,
"speed_multiplier": 1.1
}
},
"minecraft:cow_adult": {
"minecraft:experience_reward": {
"on_bred": "Math.Random(1,7)",
"on_death": "query.last_hit_by_player ? Math.Random(1,3) : 0"
},
"minecraft:loot": {
"table": "loot_tables/entities/cow.json"
},
"minecraft:behavior.breed": {
"priority": 3,
"speed_multiplier": 1.0
},
"minecraft:breedable": {
"require_tame": false,
"breed_items": "wheat",
"breeds_with": {
"mate_type": "minecraft:cow",
"baby_type": "minecraft:cow",
"breed_event": {
"event": "minecraft:entity_born",
"target": "baby"
}
}
},
"minecraft:interact": {
"interactions": [
{
"on_interact": {
"filters": {
"all_of": [
{ "test": "is_family", "subject" : "other", "value" : "player"},
{ "test": "has_equipment", "domain": "hand", "subject": "other", "value": "bucket:0"}
]
}
},
"use_item": true,
"transform_to_item": "bucket:1",
"play_sounds": "milk",
"interact_text": "action.interact.milk"
}
]
}
}
},
"components": {
"minecraft:type_family": {
"family": [ "cow", "mob" ]
},
"minecraft:breathable": {
"total_supply": 15,
"suffocate_time": 0
},
"minecraft:navigation.walk": {
"can_path_over_water": true,
"avoid_water": true,
"avoid_damage_blocks": true
},
"minecraft:movement.basic": {
},
"minecraft:jump.static": {
},
"minecraft:can_climb": {
},
"minecraft:collision_box": {
"width": 0.9,
"height": 1.3
},
"minecraft:nameable": {
},
"minecraft:health": {
"value": 10,
"max": 10
},
"minecraft:hurt_on_condition": {
"damage_conditions": [
{
"filters": { "test": "in_lava", "subject": "self", "operator": "==", "value": true },
"cause": "lava",
"damage_per_tick": 4
}
]
},
"minecraft:movement": {
"value": 0.25
},
"minecraft:despawn": {
"despawn_from_distance": {}
},
"minecraft:behavior.float": {
"priority": 0
},
"minecraft:behavior.panic": {
"priority": 1,
"speed_multiplier": 1.25
},
"minecraft:behavior.mount_pathing": {
"priority": 2,
"speed_multiplier": 1.5,
"target_dist": 0.0,
"track_target": true
},
"minecraft:behavior.breed": {
"priority": 3,
"speed_multiplier": 1.0
},
"minecraft:behavior.tempt": {
"priority": 4,
"speed_multiplier": 1.25,
"items": [
"wheat"
]
},
"minecraft:behavior.follow_parent": {
"priority": 5,
"speed_multiplier": 1.1
},
"minecraft:behavior.random_stroll": {
"priority": 6,
"speed_multiplier": 0.8
},
"minecraft:behavior.look_at_player": {
"priority": 7,
"look_distance": 6.0,
"probability": 0.02
},
"minecraft:behavior.random_look_around": {
"priority": 9
},
"minecraft:leashable": {
"soft_distance": 4.0,
"hard_distance": 6.0,
"max_distance": 10.0
},
"minecraft:balloonable": {
},
"minecraft:rideable": {
"seat_count": 1,
"family_types": [
"zombie"
],
"seats": {
"position": [ 0.0, 1.105, 0.0 ]
}
},
"minecraft:physics": {
},
"minecraft:pushable": {
"is_pushable": true,
"is_pushable_by_piston": true
},
"minecraft:conditional_bandwidth_optimization": {
},
"minecraft:behavior.nearest_attackable_target":{
"priority": 2,
"must_see":true,
"reselect_targets": true,
"within_radius": 25.0,
"entity_types":[
{
"filters":{
"test": "is_family", "subject": "other", "value": "player"
},
"max_dist":32
}
]
},
"minecraft:behavior.melee_attack": {
"priority": 3
},
"minecraft:attack":{
"damage": 3
}
},
"events": {
"minecraft:entity_spawned": {
"randomize": [
{
"weight": 95,
"trigger": "minecraft:spawn_adult"
},
{
"weight": 5,
"add": {
"component_groups": [
"minecraft:cow_baby"
]
}
}
]
},
"minecraft:entity_born": {
"add": {
"component_groups": [
"minecraft:cow_baby"
]
}
},
"minecraft:entity_transformed": {
"remove": {
},
"add": {
"component_groups": [
"minecraft:cow_adult"
]
}
},
"minecraft:ageable_grow_up": {
"remove": {
"component_groups": [
"minecraft:cow_baby"
]
},
"add": {
"component_groups": [
"minecraft:cow_adult"
]
}
},
"minecraft:spawn_adult": {
"add": {
"component_groups": [
"minecraft:cow_adult"
]
}
}
}
}
}
enable experimental featurs. to think after a day I would not realize that was all I had to do.
Problem:
This pack is missing one or more dependencies. Would you like to apply it anyway?
I was also following Microsoft's Introduction to Behavior Packs tutorial. This was the error the game provided when I tried to load my behavior pack into a new world. Sure enough, my cows did not attack me :-(
Solution #1:
I needed to do 2 things to resolve this error.
1. Correct the typo in the name of the entities folder.
As the Troubleshooting section suggests, check the spelling of this and other folders!
2. Remove the entry in invalid_known_packs for my behavior pack.
// com.Mojang > minecraftpe > invalid_known_packs.json
// This was part of the file.
{
"file_system" : "RawPath",
"from_disk" : true,
"hashes" : [ "gc9MQR+ZUuk6kivtMInudDFbammayhdk5vdSMVUzFP4=" ],
"path" : "C:/Users/<my user>/AppData/Local/Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang/development_behavior_packs/MadCows",
"uuid" : "<my uuid>",
"version" : "1.0.0"
},
It appears that Minecraft will remember previously bad behavior packs, and it will not attempt to load them again! Once I removed the above entry, the cows attacked me as expected. :-)
Solution #2:
Sometimes this error is an error, and when I play the game anyway, my mod works as expected.

Elasticsearch multiple range error

I have a problem with Elasticsearch
The following json values work in my local server but not in the remote server.
ERROR:query doesn't support multiple fields, found [date] and [price]
post.json
{
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "product:DESKTOP"
}
},
{
"range": {
"date": {
"gt": "2018-04-24",
"lte": "2018-06-24"
},
"price": {
"gt": 0,
"lte": 2000
}
}
}
]
}
},
"from": 10,
"size": 200 }
Where do I mistake? Thank you for answers
You can only specify one field per range query.
Try including two separate range queries. They'll be AND'd together, since they both show up in your must clause.
{
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "product:DESKTOP"
}
},
{
"range": {
"date": {
"gt": "2018-04-24",
"lte": "2018-06-24"
}
}
},
{
"range": {
"price": {
"gt": 0,
"lte": 2000
}
}
}
]
}
},
"from": 10,
"size": 200
}
You need multiple range queries, like this:
{
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "product:DESKTOP"
}
},
{
"range": {
"date": {
"gt": "2018-04-24",
"lte": "2018-06-24"
}
}
},
{
"range": {
"price": {
"gt": 0,
"lte": 2000
}
}
}
]
}
},
"from": 10,
"size": 200
}

Elastic search to include boundary value time stamp

I am trying to include the boundary values in response, but it always rounds up to the nearest end time according to the interval.
For eg, if I ask data from 10:20 to 10:42 , at 5 mins interval, It will return data for
10:20 - 10:25 - 10:30 - 10:30 - 10:35 - 10:40 but the last 10:40-1:42 is never returned, How can I do this. Here is the query and response.
Query
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [{
"range": {
"timestamp": {
"gte": 1486443000000,
"lte": 1486446240000
}
}
}, {
"term": {
"applicationId": "******"
}
}, {
"term": {
"hostId": "*******"
}
}]
}
}
}
},
"filter": {
"limit": {
"value": 0
}
},
"aggs": {
"time": {
"histogram": {
"field": "timestamp",
"interval": 300000,
"min_doc_count": 0,
"extended_bounds": {
"min": 1486443000000 ,
"max": 1486446240000
}
},
"aggs": {
"establishedConnections": {
"sum": {
"field": "establishedConnections"
}
}
}
}
},
"sort": {
"timestamp": {
"order": "desc"
}
}
}
Response
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 21,
"successful": 21,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
},
"aggregations": {
"time": {
"buckets": [
{
"key_as_string": "2017-02-07T04:50:00.000Z",
"key": 1486443000000,
"doc_count": 50,
"establishedConnections": {
"value": 13
}
},
{
"key_as_string": "2017-02-07T04:55:00.000Z",
"key": 1486443300000,
"doc_count": 50,
"establishedConnections": {
"value": 20
}
},
{
"key_as_string": "2017-02-07T05:00:00.000Z",
"key": 1486443600000,
"doc_count": 50,
"establishedConnections": {
"value": 7
}
},
{
"key_as_string": "2017-02-07T05:05:00.000Z",
"key": 1486443900000,
"doc_count": 50,
"establishedConnections": {
"value": 14
}
},
{
"key_as_string": "2017-02-07T05:10:00.000Z",
"key": 1486444200000,
"doc_count": 50,
"establishedConnections": {
"value": 13
}
},
{
"key_as_string": "2017-02-07T05:15:00.000Z",
"key": 1486444500000,
"doc_count": 50,
"establishedConnections": {
"value": 12
}
},
{
"key_as_string": "2017-02-07T05:20:00.000Z",
"key": 1486444800000,
"doc_count": 50,
"establishedConnections": {
"value": 9
}
},
{
"key_as_string": "2017-02-07T05:25:00.000Z",
"key": 1486445100000,
"doc_count": 50,
"establishedConnections": {
"value": 14
}
},
{
"key_as_string": "2017-02-07T05:30:00.000Z",
"key": 1486445400000,
"doc_count": 50,
"establishedConnections": {
"value": 19
}
},
{
"key_as_string": "2017-02-07T05:35:00.000Z",
"key": 1486445700000,
"doc_count": 50,
"establishedConnections": {
"value": 13
}
},
{
"key_as_string": "2017-02-07T05:40:00.000Z",
"key": 1486446000000,
"doc_count": 40,
"establishedConnections": {
"value": 8
}
}
]
}
}
}
The thing is, that in the aggregations part in query, you asked for this:
"aggs": {
"time": {
"histogram": {
"field": "timestamp",
"interval": 300000,
"min_doc_count": 0,
"extended_bounds": {
"min": 1486443000000 ,
"max": 1486446240000
}
},
"aggs": {
"establishedConnections": {
"sum": {
"field": "establishedConnections"
}
}
}
}
}
and in the interval value, you specified 300000 which in milliseconds is exactly 5 minutes, that's why the last interval from 10:42 is discarded, and all document from this interval are placed under key 10:40.
To make this more formal:
When the aggregation executes, the time field of every document will be evaluated and will be rounded down to its closest bucket. Here is the rounding function that is used:
bucket_key = Math.floor((value - offset) / interval) * interval + offset

How to parse Json response and truncate child nodes

This is the JSON response I am trying to parse:
{
"data": {
"Content": {
"id": 26,
"name": "Dashboard1"
},
"List": [
{
"ListContent": {
"id": 178,
"name": "Card-144"
},
"cards": [
{
"id": 1780,
"configuration": {
"id": 7178,
"name": "Emp"
}
}
]
},
{
"ListContent": {
"id": 179,
"name": "Card-14"
},
"cards": [
{
"id": 1798,
"configuration": {
"id": 1789,
"name": "RandomColumns"
}
}
]
},
{
"ListContent": {
"id": 180,
"name": "Card-1"
},
"cards": [
{
"id": 18080,
"configuration": {
"id": 1080,
"allow": true
}
}
]
},
{
"ListContent": {
"id": 181,
"name": "Card-14"
},
"cards": [
{
"id": 18081,
"configuration": {
"id": 1881,
"name": "Functions"
}
}
]
},
{
"ListContent": {
"id": 182,
"name": "Card-1443"
},
"cards": [
{
"id": 1782,
"configuration": {
"id": 1802,
"name": "Emp-O"
}
}
]
}
]
}
}
From the Json, I need to extract "id"s under the "ListContent" nodes and store it in an array. Also, will need to ignore "id"s under the child nodes.
Here is a groovy script I am trying to achieve this with,
def CList = ""
import groovy.json.JsonSlurper
def jsonRespData = context.expand( '${TestStep#Response#$.data.List}' )
def outputResp = new JsonSlurper().parseText(jsonRespData)
outputResp.id.each()
{log.info( ":"+ it)
CList=CList.concat(it.toString()).concat(',')}
log.info (CList)
So, the array that I am expecting is CList [178,179,180,181,182]
but I am currently getting null.
What should be the correct groovy to only read "id" from "ListContent" and write it to an array?
Any help would be really appreciated.
Thanks in advance.
You can just use the (implicit) spread operator like this:
def json = new groovy.json.JsonSlurper().parse('/tmp/x.json' as File)
//
def i = json.data.List.ListContent.id
assert i == [178, 179, 180, 181, 182]
// with explicit spread operator
def e = json.data.List*.ListContent*.id
assert e == [178, 179, 180, 181, 182]
def str = '''
{
"data": {
"Content": {
"id": 26,
"name": "Dashboard1"
},
"List": [
{
"ListContent": {
"id": 178,
"name": "Card-144"
},
"cards": [
{
"id": 1780,
"configuration": {
"id": 7178,
"name": "Emp"
}
}
]
},
{
"ListContent": {
"id": 179,
"name": "Card-14"
},
"cards": [
{
"id": 1798,
"configuration": {
"id": 1789,
"name": "RandomColumns"
}
}
]
},
{
"ListContent": {
"id": 180,
"name": "Card-1"
},
"cards": [
{
"id": 18080,
"configuration": {
"id": 1080,
"allow": true
}
}
]
},
{
"ListContent": {
"id": 181,
"name": "Card-14"
},
"cards": [
{
"id": 18081,
"configuration": {
"id": 1881,
"name": "Functions"
}
}
]
},
{
"ListContent": {
"id": 182,
"name": "Card-1443"
},
"cards": [
{
"id": 1782,
"configuration": {
"id": 1802,
"name": "Emp-O"
}
}
]
}
]
}
}
'''
def outputResp = new groovy.json.JsonSlurper().parseText(str)
outputResp.data.List.collect { it.ListContent.id }
As you already have List from (context.expand( '${TestStep#Response#$.data.List}' )) , you can simply do:
outputResp.collect { it.ListContent.id }
Above returns an ArrayList.

Elastic Search geohashes return full details not just doc_count

I am working on a property aggrigation website that would store hundred of thosuands of properties. To map areas I am using Elastic Search's GEO Hashing to reduce the number of matches returned for a given zoom level.
The code to generate the hashes is as follows:
`GET _search
{
"from": 0,
"size": 0,
"query": {
"match_all": {}
},
"filter": {
"and": [{
"range": {
"property.price": {
"lte": 1000000000
}
}
}, {
"geo_bounding_box": {
"property.location": {
"top_left": {
"lat": 42.88679,
"lon": -73.5081419
},
"bottom_right": {
"lat": 41.2390897,
"lon": -69.9279921
}
}
}
}, {
"term": {
"property.rental": false
}
}, {
"term": {
"property.country": "US"
}
}]
},
"sort": [{
"property.price": "asc"
}],
"facets": {
"stat1": {
"statistical": {
"field": "price"
}
}
},
"aggs": {
"geohash": {
"filter": {
"geo_bounding_box": {
"property.location": {
"top_left": {
"lat": 42.88679,
"lon": -73.5081419
},
"bottom_right": {
"lat": 41.2390897,
"lon": -69.9279921
}
}
}
},
"aggregations": {
"locations": {
"geohash_grid": {
"field": "location",
"precision": 8
}
}
}
}
}
}`
The resulting JSON comes back with the number of matches per GeoHash and is working, except that there doesnt seem to be any way to include the property details in the result, or include an ID to get back to it when clicked?
The result is as follows:
`{
"took": 94,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 13,
"max_score": 0,
"hits": []
},
"facets": {
"stat1": {
"_type": "statistical",
"count": 50,
"total": 90640800,
"min": 1,
"max": 19500000,
"mean": 1812816,
"sum_of_squares": 628677324820002,
"variance": 9287244646544.04,
"std_deviation": 3047498.0962330457
}
},
"aggregations": {
"geohash": {
"doc_count": 16,
"locations": {
"buckets": [
{
"key": "drt05n43",
"doc_count": 2
},
{
"key": "drt0v0q8",
"doc_count": 1
},
{
"key": "drt0sr3e",
"doc_count": 1
},
{
"key": "drt0kgr8",
"doc_count": 1
},
{
"key": "drt07sdk",
"doc_count": 1
},
{
"key": "drt075vd",
"doc_count": 1
},
{
"key": "drt05n19",
"doc_count": 1
},
{
"key": "drt05jgv",
"doc_count": 1
},
{
"key": "drsbrgvh",
"doc_count": 1
},
{
"key": "drmpgznd",
"doc_count": 1
},
{
"key": "drmpft6c",
"doc_count": 1
},
{
"key": "drmpe6bg",
"doc_count": 1
},
{
"key": "drmp7ybz",
"doc_count": 1
},
{
"key": "drmgkj77",
"doc_count": 1
},
{
"key": "drkzzj3d",
"doc_count": 1
}
]
}
}
}
}`
Any help in adding additional property data to the result would be HUGELY appreciated.
Thanks :)
p.s. sorry about the code intendation, SO's code detection with JSON is a little weird.
You could probably use nested aggregations:
http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/nested-aggregation.html
Using elastic.js from http://www.fullscale.co/elasticjs/
ejs.GeoHashGridAggregation('Geohash-Grid')
.field('Geohash')
.precision(precision)
.aggregation(
ejs.TermsAggregation('HouseType').field('HouseType')
)
.aggregation(
ejs.TermsAggregation('HouseColor').field('HouseColor')
)
);
But that is just one example. The output will then have nested aggregation counts for documents that match each geohash.