Group by date and then by city on Rails - ruby-on-rails

I have an api that its output must look like:
[
{
"store": "store",
"date": "2020/05/03",
"address": {
"city": "city1"
"address_line_1": "address"
},
"sales_count": 10,
},
{
"store": "store",
"date": "2020/05/03",
"address": {
"city": "city2"
"address_line_1": "address"
},
"sales_count": 21,
},
]
I know how to handle the grouping and the sales count, but I'm having issues with grouping by city
Store.first.sales.group(:date).count would be the sales_count but I'm not sure how to include the group by address.
Taking into account that address = Store.first.sales.first.address
This means that a store has many sales and each sale has an address.

Since you're not only just want to count sales but also return data, then you should prefer PARTITION BY to GROUP BY.
You can PARTITION BY combine date, address:
SELECT store, date, address,
COUNT(sales) OVER (PARTITION BY date, address) AS sales_count
FROM _
Beside that, if you do nothing with data but return them, then the best practice is just call sql directly from adapter (so we avoid the creation of ActiveRecord model objects was causing all sorts of memory contention problem)
result = ActiveRecord::Base.connection.execute(
"SELECT store, date, address,
COUNT(sales) OVER (PARTITION BY date, address) AS sales_count
FROM _"
)
result.each do |msg|
# json serialize ???
end

Related

Active Record query array of Json

I have a json column (is an array of objects) in my db containing the many categories related to a product like this:
[
{
"id": 1,
"name": "Category X"
},
{
"id": 2,
"name": "Category Y"
},
...
]
I need to translate into active record query the following PostgreSQL query:
SELECT * FROM products p, json_array_elements(p.category) as data
WHERE data ->>'name' = 'Sport';
Some of queries that I tried:
sports = Product.where("category ->>'name' = ?", "Sport")
Which returns an empty array (It is wrong since I have records with Sport category in my db)
sports = Product.where("category #> ?", [{name: "Sport"}])
Which raises: TypeError: can't quote Hash
sports = Product.where("category #> ?","{name: 'Sport'}")
Which raises: ERROR: operator does not exist: json #> unknown
and the Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
So I tried:
sports = Product.where("category #> ?", "[{'name': 'Sport'}]")
and
sports = Product.where("category #> ?", "[{'name': 'Sport'}]".to_json)
and some other queries all without success.
These links:
PostgreSQL functions-json
active record querying
didn't help much.
The reason why you're getting a PG::UndefinedFunction: exception ("operator does not exist: json #> unknown") is because the #> operator is meant to be used in jsonb data type columns, and your products.category column isn't.
For that you can; or to update the data type of the category column, or to explicitly cast the column at the moment of performing the query:
Product.where('category::jsonb #> ?', [{ name: 'Sport' }].to_json)
This:
Product.where("category #> ?", "[{'name': 'Sport'}]")
isn't going to work, since it's not valid syntax.

Postgres: select data to jsonb object

I'm new to json in postgres, so please don't throw anything at me. I'm trying to select data to jsonb object. I plan to use it for update from select. Right now it looks like this:
select to_jsonb(full_address) as full_address
from (
select "user".living_addr as living_id,
"user".living_addr_path as living_path,
null as living_house,
"user".address_level_id as registration_id,
"user".address_path as registration_path,
null as registration_house,
"user".work_addr as work_id,
"user".work_addr_path as work_path,
null as work_house,
public."user".user_id
from public."user"
) full_address
group by user_id, full_address
order by user_id
But I need also "living_id", "living_path", "living_house" to be into the object like this:
{
"living": {"id", "path", "house"}
}
and same for registration, work and learn.
Also, I don't need user_id in result object.
Tried to use subqueries like:
select to_jsonb(living) as living,
to_jsonb(registration) as registration,
...
from (
select "user".living_addr as id,
"user".living_addr_path as path,
null as house
from public."user"
) living,
(
select "user".address_level_id as id,
"user".address_path as path,
null as house
from public."user"
) registration
... etc
But, right now the result is wrong without grouping, and I can't find a clue how to use group by in this. There should be another simpler way I don't see.
The result object should look like this:
{
"work": {"id": ..., "path": [..., ...], "house": null},
"living": {"id": ..., "path": [..., ...], "house": null},
"registration": {"id": ..., "path": [..., ...], "house": null}
}
Is there a way to do this in postgres 9.6?
Yep, it's much more simple:
select jsonb_build_object(
'registration', jsonb_build_object('id', u.address_level_id, 'path', u.address_path, 'house', null),
'living', jsonb_build_object('id', u.living_addr, 'path', living_addr_path, 'house', null),
'work', jsonb_build_object('id', u.work_addr, 'path', u.work_addr_path, 'house', null)
)
from public.user u
And no update from select needed, just update.

Render JSON and pair records from model

I am working with rails API , and I want to render JSON file but with specific way.
I have a model with named Store, and in this model, i have records like State and City. My problem is that I want render JSON to looks like this:
{
"Arizona": [
"Phoenix",
"Tucson"
],
"California": [
"Anaheim",
"Los Angeles",
"San Diego",
"San Francisco"
],
"Colorado": [
"Denver"
],
}
I may have in model many records with the name Colorado or with the name California, but every California record have its own city name, for example:
this is my model
| state | city |
-----------------------
|California| Anaheim |
|Colorado | Denver |
|California| San Diego|
and so on ..
so I want to pair every city that belongs to the unique state, so my JSON would show only one time the State name .
any suggestion?
Try this:
Model.select(:state, :city).group{|add| address.state}
This will return:
{"California" => [ModelObject2, ModelObject2 ], "Colarado" =>
[ModelObject1]}
Now we need to replace second object part with the city name so loop over the second part and get city from that object and then to_json to convert into json object.
Model.select(:state, :city).group{|add| address.state}.each{|_, v| v.replace(v.map {|add| add.city})}.to_json
Hope this will help you!!
ref

neo4j cypher nested collect

Imagine a photo album schema w/ Users, Albums, and Photos:
User -[owns]-> Album -[contains]-> Photo
Can I do a nested collect to get Photos nested in Albums, and Albums nested in User? I'd like results similar to:
{ "users": [
{ "name": "roger dodger",
"albums": [
{ "album": "album1",
"photos": [
{"url": "photo1.jpg"},
{"url": "photo2.jpg"}
]
}
]
}
]
}
This seems close but I could not modify it to suit my needs: Nested has_many relationships in cypher
(Could the problem be that neo4j 2.0 web console doesn't support the json syntax in that example?)
Try this query:
MATCH (a:USER)-[:owns]->(b:ALBUM)-[:CONTAINS]->(c:PHOTO)
WITH a,b,{url: c.name} as c_photos
WITH a,{album: b.name , photos: collect(c_photos)} as b_albums
WITH {name: a.name, albums: collect(b_albums)} as a_users
RETURN {users: collect(a_users)}
Edit
To get all properties of a node you can use string representation of the node and then parse it separately using java etc
MATCH (a:User)
WITH {user: str(a)} as users
RETURN {users: collect(users)}

Complex Active Record Association

User
first_name: "Johnny"
age: 15
Car
name: "Mazda"
Car
name: "BMW"
I would like results that look like
[ {"first_name": "Johnny", "age": 15, cars: [ { "name": "Mazda" }, { "name" : "BMW" } ] } ]
Is it possible to do this in Rails? So far I can get the Users car by typing johnny.cars but I'd like the data structure to also hold the values of the parent.
I was toying with the idea of using named_scopes and transient attributes but no luck so far any ideas/help is greatly appreciated.
You Could actually retrieve all the records from the other table using :includes statement
includes is magically syntax where in you can eager load all the assocaited records of a record.
Example In your case
User has_many cars
so If you do
#users = User.includes(:cars)
Now this would load all the user records and will eagerload all the cars records for each user objects
so if you loop through a user object and do
<% #users.each do |user| %>
<%= user.cars %>
<%end%>
user.cars wont fire a seperate query to fetch the all cars for the users instead it will fetch those record eager loaded using the includes clause
This technique is widely used to avoid N+1 query problem
Google for N+1 to know more on it
Hope this Help

Resources