fill a JSON file with embedded arrays from Rails - ruby-on-rails

I have a simple "rss" (ApplicationRecord) table indexed by an id. I would like to have a structured JSON that group each user from a family in an array structure. And then each family in a global array. How can I do that ?
my current plain code to put my data in a json file is :
json.rss #rss do |rs|
json.id rs.id
json.name rs.name
json.family rs.family
json.lastdate rs.lastdate
json.last rs.last
json.s1w rs.s1w
json.s2w rs.s2w
end
But the target file that I want is this one :
{
"rss": [
{
"familyname": "Smith",
"children": [
{
"id": "1",
"name": "bob",
"lastdate": "2010-09-23",
"last": "0.88",
"s1w": "0.83",
"s2w": "0.88"
},
{
"id": 2,
"name": "Mary",
"lastdate": "2011-09-23",
"last": "0.89",
"s1w": "0.83",
"s2w": "0.87"
}
]
},
{
"familyname": "Wesson",
"children": [
{
"id": "1",
"name": "john",
"lastdate": "2001-09-23",
"last": "0.88",
"s1w": "0.83",
"s2w": "0.88"
},
{
"id": 2,
"name": "Bruce",
"lastdate": "2000-09-23",
"last": "0.89",
"s1w": "0.83",
"s2w": "0.87"
}
]
}
]
}

The grouping you are trying to achieve can be done in Ruby with:
#rss.group_by(&:family).values
This is assuming #rss is an array-like collection of objects that have a .family method. The result: is an array of arrays of objects grouped by family.
Now it will be up to use to use Jbuilder's array! method to build the desired JSON output.

Related

Neo4j recursive cypher query resulting in nested JSON structure

I am trying to figure out cypher query in order to get nested JSON structure as a result. Below I present an example of the graph.
MATCH (user:User {name:"User_1"})
OPTIONAL MATCH (user)-[rel*]->(subUser:User)
RETURN *
Query above allows me to get all the nodes and relationships required to transform everything to JSON structure I want but that requires me to process everything after getting the result from querying the database. To achieve that I need to match identity of nodes and relationship in order to get the nested JSON.
I was wondering if it is possible to achieve that directly from building cypher query.
Important thing is that we do not know how many levels of "child" Users we have starting from User_1
Expected JSON structure:
{
"user": "User_1",
"children": [
{
"user": "User_2",
"children": [
{
"user": "User_5",
"children": []
}
]
},{
"user": "User_3",
"children": [
{
"user": "User_6",
"children": []
}
]
},{
"user": "User_4",
"children": []
}
]
}
Is it possible?
As suggested in the comments by #nimrod serok, you can use the apoc.convert.toTree method, it will give you the tree-structured JSON, as desired, with one caveat, the keys of the JSON will be different. For the data:
MERGE (u1:User{name: 'User1'})
MERGE (u2:User{name: 'User2'})
MERGE (u3:User{name: 'User3'})
MERGE (u4:User{name: 'User4'})
MERGE (u5:User{name: 'User5'})
MERGE (u6:User{name: 'User6'})
MERGE (u1)-[:POINTS]->(u2)-[:POINTS]->(u5)
MERGE (u1)-[:POINTS]->(u3)-[:POINTS]->(u6)
MERGE (u1)-[:POINTS]->(u4)
The query:
MATCH (user:User {name:"User1"})
OPTIONAL MATCH path = (user)-[:POINTS*]->(subUser:User)
WITH collect(path) AS paths
CALL apoc.convert.toTree(paths, true, {nodes: {User: ['name']}})
YIELD value
RETURN value
produces the output:
{
"_type": "User",
"name": "User1",
"_id": 4,
"points": [
{
"_type": "User",
"name": "User3",
"_id": 6,
"points": [
{
"_type": "User",
"name": "User6",
"_id": 9
}
]
},
{
"_type": "User",
"name": "User2",
"_id": 5,
"points": [
{
"_type": "User",
"name": "User5",
"_id": 8
}
]
},
{
"_type": "User",
"name": "User4",
"_id": 7
}
]
}
as you can see, the relationship type POINTS, comes in place of children, and the key name comes for the user name. The other fields _type and _id can be ignored.
apoc.convert.toTree() is certainly the best answer for the question you asked.
If one is interested in a text output then ORDPATH would be another solution. ORDPATH is a concatenated bitstring which sorts in hierarchical order. More on this at this link. A Neo4j user defined function implementing this is at GitHub.

Swift iOS how to handle JSON nested array in object class?

I would like to create a Swift TableView for all available sizes of coffee within a specific type. With this JSON tree, how can you structure the class to create an array for the type specific sizes?
The JSON Tree is structured as follows:
{
"_id": "60ba1ab72e35f2d9c786c610",
"types": [
{
"_id": "60ba1a062e35f2d9c786c56d",
"name": "Ristretto",
"sizes": [
"60ba18d13ca8c43196b5f606",
"60ba3368c45ecee5d77a016b"
],
"extras": [
"60ba197c2e35f2d9c786c525"
]
},
{
"_id": "60be1db3c45ecee5d77ad890",
"name": "Espresso",
"sizes": [
"60ba3368c45ecee5d77a016b",
"60ba33dbc45ecee5d77a01f8"
],
"extras": [
"60ba34a0c45ecee5d77a0263"
]
},
{
"_id": "60be1eabc45ecee5d77ad960",
"name": "Cappuccino",
"sizes": [
"60ba18d13ca8c43196b5f606",
"60ba3368c45ecee5d77a016b",
"60ba33dbc45ecee5d77a01f8"
],
"extras": [
"60ba197c2e35f2d9c786c525",
"60ba34a0c45ecee5d77a0263"
]
}
],
"sizes": [
{
"_id": "60ba18d13ca8c43196b5f606",
"name": "Large",
"__v": 0
},
{
"_id": "60ba3368c45ecee5d77a016b",
"name": "Venti"
},
{
"_id": "60ba33dbc45ecee5d77a01f8",
"name": "Tall"
}
],
"extras": [
{
"_id": "60ba197c2e35f2d9c786c525",
"name": "Select the amount of sugar",
"subselections": [
{
"_id": "60ba194dfdd5e192e14eaa75",
"name": "A lot"
},
{
"_id": "60ba195407e1dc8a4e33b5e5",
"name": "Normal"
}
]
},
{
"_id": "60ba34a0c45ecee5d77a0263",
"name": "Select type of milk",
"subselections": [
{
"_id": "611a1adeff35e4db9df19667",
"name": "Soy"
},
{
"_id": "60ba348d8c75424ac5ed259e",
"name": "Oat"
},
{
"_id": "60ba349a869d7a04642b41f4",
"name": "Cow"
}
]
}
]
}
My classes: (I can currently load a TableView with the coffee sizes, but not the type specific sizes)
import Foundation
import UIKit
class Types: Codable {
let types: [CoffeeType]
init(types: [CoffeeType]) {
self.types = types
}
}
class Sizes: Codable {
let sizes: [CoffeeType]
init(sizes: [CoffeeType]) {
self.sizes = sizes
}
}
class CoffeeType: Codable {
let _id: String
let name: String
init(_id: String, name: String) {
self._id = _id
self.name = name
}
}
The app is structured like this: HomeViewController is a TableView of Types. When you click on a Type, you transition to SelectSizeViewController, to which I have already assigned a Type through the segue. On SelectSizeViewController, I would like to display the list of specific sizes.
use QuickType to get the model this is quite helpful. you will be getting the model easily(suggestion). I think you are using the wrong model.
if your Base model struct is correct it should be something like this
struct Coffie: Codable {
let id: String
let types: [TypeElement]
let sizes: [Size]
let extras: [Extra]
enum CodingKeys: String, CodingKey {
case id
case types, sizes, extras
}
}
from here itself you can get the type and sizes with corresponded id's you can filter size values from sizes array

how to merge Hashes in Ruby/Rails

I have a Hash like this, which should be "merged" to its uniq nested values
[
{
"slug": "color",
"values": [{ "slug": "amethyst" },
{ "slug": "coral" }],
},
{
"slug": "color",
"values": [{ "slug": "amethyst" }],
},
{
"slug": "power-source",
"values": [{ "slug": "110V"}],
}
]
at the same time it should count the duplicate values but made uniq in an items array:
{ "slug": "color",
"items": [
{
"slug": "amethyst",
"count": 2
},
{
"slug": "coral",
"count": 1
}]
},
{
"slug": "power-source",
"items": [
{
"slug": "110V",
"count": 1
}]
}
]
is there a "Rails method" to achieve this?
Thank you
I think there's nothing built-in in Rails that allows you to get such a custom requirement, but you can achieve it by playing around with different methods and their return values:
data
.group_by { |hash| hash[:slug] }
.transform_values do |values|
values
.flat_map { |vals| vals[:values] }
.group_by { |value| value[:slug] }
.transform_values(&:count)
end.map do |slug, items|
[slug, items.map { |item, count| {slug: item, count: count} }]
end.map { |slug, items| {slug: slug, items: items} }
# [{:slug=>"color",
# :items=>[{:slug=>"amethyst", :count=>2}, {:slug=>"coral", :count=>1}]},
# {:slug=>"power-source", :items=>[{:slug=>"110V", :count=>1}]}]
As you see, you can first group every hash in the array by their slug value, then transform the values that hash contains, mapping and flattening every array by their values key and then grouping to get their total.
After that you can just create the hash with its keys/values you need.
It might simplify the things a bit if you end up with a single hash, whose keys are the "slugs" and contains the items as its values.

Storing a List in a Vertex using Gremlin and Azure Cosmos Graph

I am trying to store a list of changes made to a Vertex in the Vertex itself. Ideally I would want something like this:
{
"id": "95fcfa87-1c03-436d-b3ca-340cea926ee9",
"label": "person",
"type": "vertex",
"log": [{
"user": "user#user.dk",
"action": "update",
"timestamp": "22-03-2017",
"field": "firstName",
"oldValue": "Marco"
}
]
}
Using this method chain I am able to a achieve the following structure
graph.addV('person')
.property('firstName', 'Thomas')
.property(list, 'log', '22-03-2017')
.properties('log')
.hasValue('22-03-2017', '21-03-2017')
.property('user','user#user.dk')
.property('action', 'update')
.property('field', 'firstName')
.property('oldValue', 'Marco')
{
"id": "95fcfa87-1c03-436d-b3ca-340cea926ee9",
"label": "person",
"type": "vertex",
"properties": {
"firstName": [{
"id": "f23482a9-48bc-44e0-b783-3b74a2439a11",
"value": "Thomas"
}
],
"log": [{
"id": "5cfa35e1-e453-42e2-99b1-eb64cd853f22",
"value": "22-03-2017",
"properties": {
"user": "user#user.dk",
"action": "update",
"field": "firstName",
"oldValue": "Marco"
}
}
]
}
}
However this seems overly complex, as I will have to store a value and add properties to it.
Is it possible to add anonymous objects (i.e. without id and value) with the above mentioned data?
Not an actual solution to storing proper objects in a history log, but if you just use it as a log and don't have to access or query it by its properties, you could just put the serialised JSON in the value?
Something like along these lines should approximate the structure you're requesting:
dynamic entry = new JObject();
entry.user = "user#user.dk";
entry.action = "update";
entry.timestamp = "22-03-2017 12:34:56";
entry.field = "firstName";
entry.oldValue = "Marco";
graph.addV('person')
.property('firstName', 'Thomas')
.property(list, 'log', entry.ToString());
{
"id": "95fcfa87-1c03-436d-b3ca-340cea926ee9",
"label": "person",
"type": "vertex",
"properties": {
"firstName": [{
"id": "f23482a9-48bc-44e0-b783-3b74a2439a11",
"value": "Thomas"
}
],
"log": [{
"id": "5cfa35e1-e453-42e2-99b1-eb64cd853f22",
"value": "{\"user\":\"user#user.dk\",\"action\":\"update\",\"timestamp\":\"22-03-2017\",\"field\":\"firstName\",\"oldValue\":\"Marco\"}"
}
]
}
}
These log entries can easily be read, deserialised, used, and presented, but will not do much for queriability.

How to represent typical json information

Below JSON contains 4 items in an array. If you look at each item it is some what shows incomplete keys. I am unable to figure out how to represent the consistent data in iOS (of any UI design patterns). By looking at the below information somewhat they are interlinked to each other for example parent key value information is same as company key value and also in employees one value is same as name key value. This seems to be very typical.
{
"arays": [
{
"company": "Microchip",
"parent": "File",
"employees": [
"John",
"Mike"
]
},
{
"company": "Apple",
"mobiles": [
"111-111-1111",
"121-121-1212"
]
},
{
"company": "File",
"parent": "Apple",
"addresses": [
"2600 space center blvd",
"2700 university dr"
]
},
{
"name": "John",
"mobiles": [
"222-222-2222"
],
"addresses": [
"Time Square, NY"
]
}
]
}

Resources