Rails: create database structure for an archive - mysql

I have a general architectural question concerning the design of part of a database. I would like to implement an archive for an educational entity and have a form field, where I can query the archive and get a certain subset of entries. Everything started with only an archive of articles and lectures. I treated both as similar and used one table named resources with columns for all the data I needed in both cases. This way I could write in my Rails app something like:
Resources.find(:all).where('title LIKE ?', "%#{params[:searchTitle]}%")
and get all the resources with a certain string in its title.
Now I would like to extend the archive to comprehend a wider set of resources containing documentation of educational or research activities. I will have items as well as what you could call collections and sub collections. Items would be things like sheets, texts, images, magazines, books, music, video, drawings, models, maps. Collections would be something like courses, lectures, exercises, projects, exhibitions. A course can have multiple exercises and lectures. An exercise can have multiple projects, etc. But there might be projects without an exercise or course. I might choose to add keywords to the resources to describe content.
A query should result in a view with all related entries of single items and collections in one list.
I would usually create a table for each resource in order to have as few repeating data as possible. But I usually have one table as entry point for my queries and would have now 14 resources tables + join tables + tables such as authors. How should I set up the structure of such a database and in case I will have to create single tables for each resource: How do I query 14 tables and display the result in one list.
Thank you in advance.

in your controller action method,
resources1 = Resource1.where("title LIKE ?", "%#{params[:searchTitle]}%")
resources2 = Resource2.where("title LIKE ?", "%#{params[:searchTitle]}%")
resources3 = Resource3.where("title LIKE ?", "%#{params[:searchTitle]}%")
#total_results = resources1 + resources2 + resources3

Related

Creating a temporary table from inside Controller in Laravel PHP

I'm making a Laravel website which is a musician directory. Every Musician has many Skills and Genres.
I want the user to be able to make advanced searches by specifying various skills and genres.
The results are then to be retrieved and sorted by relevance.
Example:
User specifies skills: "Guitar", "Theory", and genres "Jazz", "Rock", "Blues".
A Musician with the skills: "Guitar", "Bass", and genres "Jazz", "Funk" gets a relevance score of 2 because he has two matching tags.
My plan is to make a temporary table inside of the MusiciansController search() function which stores all the results for the user's search.
How would I go about doing this if even possible?
I suggest making this a little easier on yourself by designing this slightly differently. Instead of thinking about a 'temporary' table, create an actual Laravel model and create all the functionality (calculations of relevance, user, etc) within.
By having a model / DB connection, you can also use Laravel relationships and call the methods on that model in a scalable way in future -- IE if you want to add new relevance calcs, or different relationships, you don't have to modify an SQL view - just add a method.
If you want to simulate a temporary table, just have a cleaner function at the start of the next search to wipe the previous records in the DB for that model.
Lastly, ask yourself if you even need to store this in a table, or can you calculate it using some set of formulae within the controller's methods.

Relationship database design - object specific many to many, do I solve with self join table or new table

Being new to relational database design, I am trying to clarify one piece of information to properly design this database. Although I am using Filemaker as the platform, I believe this is a universal question.
Using the logic of ideally having all one to many relationships, and using separate tables or join tables to solve these.
I have a database with multiple products, made by multiple brands, in multiple product categories. I also want this to be as scale-able as possible when it comes to reporting, being able to slice and dice the data in as many ways as possible since the needs of the users are constantly changing.
So when I ask the question "Does each Brand have multiple products" I get a yes, and "Does each product have multiple brands" the answer is no. So this is a one to many relationship, but it also seems that a self-join table might give me everything that I need.
This methodology also seems to go down a rabbit hole for other "product related" information such as product category, each product is tied to one product category, but only one product category is related to a product.
So I see 2 possibilities, make three tables and join them with primary and foreign keys, one for Brand, one for Product Category, and one for Products.
Or the second possibility is to create one table that has the brand and product category and product info all in one table (since they are all product related) and simply do self-joins and other query based tables to give me the future reporting requirements that will be changing over time.
I am looking for input from experiences that might point me in the right direction.
Thanks in advance!
Could you ever want to store additional information about a brand (company URL, phone number, etc.) or about a product category (description, etc.)?
If the answer is yes, you definitely want to use three tables. If you don't, you'll be repeating all that information for every single item that belongs to the same brand or same category.
If the answer is no, there is still an advantage to using three tables - it will prevent typos or other spelling inconsistencies from getting into your database. For example, it would prevent you from writing a brand as "Coca Cola" for some items and as "Coca-Cola" for other items. These inconsistencies get harder and harder to find and correct as your database grows. By having each brand only listed once in it's own table, it will always be written the same way.
The disadvantage of multiple tables is the SQL for your queries is more complicated. There's definitely a tradeoff, but when in doubt, normalize into multiple tables. You'll learn when it's better to de-normalize with more experience.
I am not sure where do you see a room for a self-join here. It seems to me you are saying: I have a table of products; each product has one brand and one (?) category. If that's the case then you need either three tables:
Brands -< Products >- Categories
or - in Filemaker only - you can replace either or both the Brands and the Categories tables with a value list (assuming you won't be renaming brands/categories and at the expense of some reporting capabilities). So really it depends on what type of information you want to get out in the end.
If you truly want your solution to be scalable you need to parse and partition your data now. Otherwise you will be faced with the re-structuring of the solution down the road when the solution grows in size. You will also be faced with parsing and relocating the data to new tables. Since you've also included the SQL and MySQL tags if you plan on connecting Filemaker to an external data source then you will definitely need to up your game structurally.
Building everything in one table is essentially using Filemaker to do Excel work and it won't cut it if you are connecting to SQL, MySQL, etc.
Self join tables are a great tool. However, they should really only be used for calculating small data points and should not be used as pivot points or foundations for your reporting features. It can grow out of control as time goes on and you need to keep your backend clean.
Use summary and sub-summary reporting features to slice product based data.
For retail and general product management solutions, whether it's Filemaker/SQL/or whatever the "Brand" or "Vendor" is it's own table. Then you would have a "Products" table (the match key being the "Brand ID").
The "Product Category" field should be a field in the "Products" table. You can manage the category values by building a standard value list or building a value list based on a "Product Category" table. The second scenario is better for long term administration.

Migrating from MySQL to MongoDB - best practices

So, it may be best to just try it out and see through some trial and error, but I'm trying to figure out the best way to migrate a pretty simple structure from mysql to mongodb. Let's say that I have a main table in mysql called 'articles' and I have two other tables, one called 'categories' and the other 'category_linkage'. The categories all have an ID and a name. The articles all have an ID and other data. The linkage table relates articles to categories, so that you can have unlimited categories related to each article.
From a MongoDB approach, would it make sense to just store the article data and category ID's that belong to that article in the same collection, thus having just 2 data collections (one for the articles and one for the categories)? My thinking is that to add/remove categories from an article, you would just update($pull/$push) on that particular article document, no?
In my opinion, a good model would look like this:
{"article_name": "name",
"category": ["category1_name", "category2_name", ...],
"other_data": "other data value"
}
So, to embed the category names directly to the article document. Updating article categories is easy, but removing a category altogether requires modifying all articles belonging to the category. If removing categories is frequent, then keeping them separate might be a good idea performance-wise.
This approach makes it also easy to make queries on the category name (no need to map name to id with a separate query).
Thus, the "correct" way to model the data depends on the assumed use case, as is typically the case with mongodb and other nosql databases.
If you have access to a Mac computer, you could give the MongoHub GUI a try. It has an "Import from MySQL" feature.

Integrated CMS Based Off Model for Rails

I have a site nearing structural completion. Essentially, it's made up of Users and Photos. However, Photos have a LOT of HABTM relationships, most of which are different kinds of tags, and others being categories, collections, etc...
My client would like to be able to have a conditional CMS based off the content being viewed for different promotional purposes or whatnot. For example, if a user is browsing the Category "Leprechauns", he may want to show html content about St. Patrick's Day or something. He may even want to easily include the browing user's name, if available. In which case, it'd be nice to have some sort of templating system. The part that makes this tricky is that these are small blocks of HTML for something like a 300x300 space in the sidebar and is NOT the primary content.
I've looked into refinery, but it seems to be too much of a complete solution. I've also thought about building in from scratch, but I don't know where to begin with treating dynamically generated pages (such as a new Category) as a recognizable object in Rails. I'd like to keep it more global than a slew of HABTM relationships, but it's looking like that might be where I'm heading. Ideally, he'd be able to make some HTML and check off "I'd like this to show on x and y Category page and b and z Collection page and for the tag Foo and for the tag bar as well as on my homepage"
Any suggestions? I'm open to finding a gem or getting a solid start on a homebrew.
UPDATE
I'm thinking of setting up some models Like the following:
cms_contents
============
id:integer
contents:text
timestamps
cms_associations
================
id:integer
cms_content_id:integer
model_id:integer
record_id:integer #optional
secondary_model_id:integer #optional
secondary_record_id:integer #optional
models
======
id:integer
name:string
Where:
cms_content would contain the HTML.
cms_associations would be an ActiveRecord model using has_many, :through
models would contain a the models the CMS content could be associated with
if record_id is not given, it associates with the model index
if record_id is given, it associated with the record of the provided model with that
id
if secondary information is given, a combination is created for other many to many
relationships
eg:
User has_many :photos
Browsing Photos for User(10)
model_id => #User model Id
record_id => 10
secondary_model_id => #Photo model id
So you could customize the content for browsing photos for specific users such as featured users or companies that may pay for advertising.
Any thoughts on this structure?
It's actually not that complicated. This is what you should do:
Introduce new object in the DB, name it htmlchunks
For every object that you'd want to associate with htmlchunks, create a join table and define habtm relationship
Modify your sidebar (for objects that have association with htmlchunks) in a way that they recognize whether there's htmlchunk associated with this particular object. For example, let's say you have a htmlchunk called "April Fools' Day" that contains simple html paragraph. In the sidebar, you'd just ask something like #category.htmlchunk? and output according to the result. You'd ideally place all this in a partial
As for creation of the htmlchunks you'd just offer simple wisiwig editor and ability to select any number of tags, categories, whatever. You'd create habtm entries between them and htmlchunks during the creation process
Let me know if you have further questions in the comments.
It's almost as if the almighty Ryan Bates is looking out for me, but the latest Railscast is on CopyCopter, which does exactly what I'm looking for, and runs as a separate app, so I don't have to worry about bogging down my main app. I suggest anyone who finds this to watch the screencast, as it seems pretty impressive.
http://railscasts.com/episodes/336-copycopter?autoplay=true

Database design of a tree-like category system

I'm using the Adjacency List Model to create categories, and it works perfectly.
When retrieving articles in a certain category (for example electronics), I would like to also retrieve the articles in the sub categories (for example electronics->cameras, or even electronics->cameras->camera lenses).
The way I am doing it now is pulling from the DB all the category id's of the sub categories of electronics, and finding all articles with a category_id in this list.
This seems to me very inefficient and time-consuming, since this could result in many queries to retrieve these sub categories.
Another way I thought of doing this is having every article associated with the whole category tree (for example an article about camera lenses will also be associated with the camera and electronics categories in MANY_MANY table), and when I retrieve all articles in electronics it will also appear.
This would add a lot of redundant data to the database though, as I might have to store 3 or 4 categories for each article. Also, it would complicate actions like moving an article to another category.
Is this the right way to go? Or is there a better/simpler way that I have not thought of?
Any help appreciated!
Have a read of this article about Nested Set Modelling: Managing Hierarchical Data in MySQL.
Using the suggested technique, you can get entire trees or subtrees in one single SELECT. It's a bit more complicated than the "normal" approach, but it's totally worth it if you're going to be doing lots of reads from the table.