Can I Order Results Using Two Columns from Different Tables? - ruby-on-rails

I have a Rails application featuring a city in the US. I'm working on a database process that will feature businesses that pay to be on the website. The goal is to feature businesses within an hour's drive of the city's location in order to make visitors aware of what is available. My goal is to group the businesses by city where the businesses in the city are listed first then the businesses from the next closest city are displayed. I want the cities to be listed by distance and the businesses within the city group to be listed by the business name.
I have two tables that I want to join in order to accomplish this.
city (has_many :businesses) - name, distance
business (belongs_to :city) - name, city_id, other columns
I know I can do something like the statement below that should only show data where business rows exist for a city row.
#businesses = City.order(“distance ASC").joins('JOIN businesses ON businesses.city_id = cities.id')
I would like to add order by businesses.name. I've seen an example ORDER BY a.Date, p.title which referencing columns from two databases.
ORDER BY a.Date, p.title
Can I add code to my existing statement to order businesses by name or will I have to embed SQL code to do this? I have seen examples with other databases doing this but either the answer is not Rails specific or not using PostgreSQL.

After lots more research I was finally able to get this working the way I wanted to.
Using .joins(:businesses) did not yield anything because it only included the columns for City aka BusinessCity and no columns for Business. I found that you have to use .pluck or .select to get access to the columns from the table you are joining. This is something I did not want to do because I foresee more columns being added in the future.
I ended up making Business the main table instead of BusinessCity as my starting point since I was listing data from Business on my view as stated in my initial question. When I did this I could not use the .joins(:business_cities) clause because it said the relation did not exist. I decided to go back to what I had originally started with using Business as the main table.
I came up with the following statement that provides all the columns from both tables ordered by distance on the BusinessCity table and name on the Business table. I was successful in added .where clauses as needed to accommodate the search functionality on my view.
#businesses = Business.joins("JOIN business_cities ON business_cities.id = businesses.business_city_id").order("business_cities.distance, businesses.name")

Related

Reducing over multiple joins in CouchDB

In my CouchDB database, I have the following models (implemented as documents in the database with different type fields):
Team: name, id (has many matches, has many fans)
Match: name, team_a, team_b, time (has many teams, has many tweets)
Fan: team_id (has many tweets)
Tweet: time, sentiment, fan_id
I want to average the tweet sentiment for each team. If I were using SQL I'd do it like this:
SELECT avg(sentiment)
FROM team
JOIN match on team.id = match.team_a OR team.id = match.team_b
JOIN fan on fan.team = team.id
JOIN tweet on (tweet.time BETWEEN match.time AND match.time + interval '1 hour') AND tweet.user = fan.id
GROUP BY team.id
However in CouchDB you can at best do 1 join in a view function, as explained in the docs (by emitting the join field as the key).
How can this be better modelled in CouchDB to allow for this query to work? I don't really want to denormalise too much, but I guess I will if I have to?
It's a bit complex, but I use what I call "tertiary indexes". The goal is to be able to write a view that is applied to another view. Unfortunately, the only way to do this is to use a view to write data to a secondary database and then have another view that works on that database. Doing this requires an outside process - I use a script that listens to the _changes feed of the primary database, and then updates the relevant documents in the secondary database when something changes.
So in your example your secondary database could consist of a single document for each team with all of the (or the latest) match/fan/tweet data in that one document. Then you write a view that extracts the sentiment (or whatever) from that secondary database.

ActiveRecord Associations should i be using 3 join tables?

i currently have 3 tables and 3 join tables
Users
Projects
Materials
a User has many Projects and Materials
a Project has many Users and Materials
a Material has many Projects and Users
each of them have their respective join tables to one another
say a Material has a column "name" and "amount". How can i form the associations so that for the same instance of materials, it has a different amount for a Project and a User?
I am currently storing "amount" in their join tables so a UserMaterial and a ProjectMaterial has different "amounts". The issue with that is when i query the materials from a User, I would have to make 2 separate queries. One to get an array of the Material names from the Materials table,
user.materials
and another to get an array of the amounts from the UserMaterial.
user.usermaterials
Is there an issue/improvement with my associations? or is there a query method to combine those 2 arrays, attaching the correct name and amount to the correct id?
Any assistance is appreciated. Thank you
If you query on user.materials, that will have to join through user_materials. If you use includes, it can get both in one query.
user_materials = #user.user_materials.includes(:material)
Then, when you loop through, the user_material.material association will already be loaded and ready for you.
user_materials.each do |um|
name = um.material.name # material is already loaded
end

Adding support for a three column join in a rails form

I'm working on an application where we have a survey, and the survey can be run at multiple locations, and each location could have a different staff member. Logically, makes sense to create a three column join table between Survey, Location, and Trainer. Seems easy enough.
The problem I'm having is associating all three in the form when submitting. I know how to create an array of locations and an array of staff members, but not clear on how to associate those two together.
Selecting both the locations and staff members is done through a collection select.
After that, I feel pretty comfortable I can write the necessary code to create the records in the join table, just looking for some ideas how to structure the HTML and/or form_for objects.

Best way to recommend Products to Users based on Interest?

Let's say that each Product has a category. I want to ask the Users to select several categories that the user is interested in, and find the Products that have the same category. This is similar to what Quora, Stumbleupon, and Pinterest all do.
What would be the best way to set this database structure in Rails? Should I create 3 tables: User, Product, and Category, and make the relations
User has many Categories & Product has many Categories?
The problem I see with this is doesn't it create, rather than reference, a new instance of Categories to each row of Users and Products?
*extra: What if I wanted subcategories? For example, if the user chose Technology, it could further ask to choose between web dev, mobile dev, hardware, etc.
You could do that kind of 'recommendation' pretty easily.
Something like this should work (N.B.: I did not test this code, but it is right in spirit):
def recommended_products
joins(:categories, :products).where("product_id not in (?)", self.products)
end
Explanation of each bit:
joins(:categories, :products): this does a SQL join of users, products, and categories. This gives you a 'table' where each user-product-category combination is in it's own row.
.where("product_id not in (?)", self.products): adds a SQL where clause to filter out all the rows that have products in the current user's list of products.
The associations are not a problem. They don't create any new instances by themselves, only if you write code that creates new instances yourself.
As for sub categories, I think you'll do better to make that it's own question, as it's easily a whole post in itself.

Single Inheritance or Polymorphic?

I'm programming a website that allows users to post classified ads with detailed fields for different types of items they are selling. However, I have a question about the best database schema.
The site features many categories (eg. Cars, Computers, Cameras) and each category of ads have their own distinct fields. For example, Cars have attributes such as number of doors, make, model, and horsepower while Computers have attributes such as CPU, RAM, Motherboard Model, etc.
Now since they are all listings, I was thinking of a polymorphic approach, creating a parent LISTINGS table and a different child table for each of the different categories (COMPUTERS, CARS, CAMERAS). Each child table will have a listing_id that will link back to the LISTINGS TABLE. So when a listing is fetched, it would fetch a row from LISTINGS joined by the linked row in the associated child table.
LISTINGS
-listing_id
-user_id
-email_address
-date_created
-description
CARS
-car_id
-listing_id
-make
-model
-num_doors
-horsepower
COMPUTERS
-computer_id
-listing_id
-cpu
-ram
-motherboard_model
Now, is this schema a good design pattern or are there better ways to do this?
I considered single inheritance but quickly brushed off the thought because the table will get too large too quickly, but then another dilemma came to mind - if the user does a global search on all the listings, then that means I will have to query each child table separately. What happens if I have over 100 different categories, wouldn't it be inefficient?
I also thought of another approach where there is a master table (meta table) that defines the fields in each category and a field table that stores the field values of each listing, but would that go against database normalization?
How would sites like Kijiji do it?
Your database design is fine. No reason to change what you've got. I've seen the search done a few ways. One is to have your search stored procedure join all the tables you need to search across and index the columns to be searched. The second way I've seen it done which worked pretty well was to have a table that is only used for search which gets a copy of whatever fields that need to be searched. Then you would put triggers on those fields and update the search table.
They both have drawbacks but I preferred the first to the second.
EDIT
You need the following tables.
Categories
- Id
- Description
CategoriesListingsXref
- CategoryId
- ListingId
With this cross reference model you can join all your listings for a given category during search. Then add a little dynamic sql (because it's easier to understand) and build up your query to include the field(s) you want to search against and call execute on your query.
That's it.
EDIT 2
This seems to be a little bigger discussion that we can fin in these comment boxes. But, anything we would discuss can be understood by reading the following post.
http://www.sommarskog.se/dyn-search-2008.html
It is really complete and shows you more than 1 way of doing it with pro's and cons.
Good luck.
I think the design you have chosen will be good for the scenario you just described. Though I'm not sure if the sub class tables should have their own ID. Since a CAR is a Listing, it makes sense that the values are from the same "domain".
In the typical classified ads site, the data for an ad is written once and then is basically read-only. You can exploit this and store the data in a second set of tables that are more optimized for searching in just the way you want the users to search. Also, the search problem only really exists for a "general" search. Once the user picks a certain type of ad, you can switch to the sub class tables in order to do more advanced search (RAM > 4gb, cpu = overpowered).

Resources