I'm still very much a noob and I've been having quite a bit of trouble figuring out how to structure my DB for my Gym/Workout Log app.
The data is to be presented in TableViews with Rows/Sections.The idea is that the end user would first select a day of the week and will name his workout, and he could have multiple workouts under the same day of the week if he wishes. Then, within each workout, he could have multiple exercises, and within each exercise, he could have an array of Weights and Repetitions that need to maintain the order in which they are pushed in (might be some trouble there since I heard that arrays do not always maintain the same order when queried).
There are a few ways that I can go about structuring my DB, but I know that I have to avoid Sub-Collections because although sub-collections will structure my DB beautifully, they are a pain to work with when it comes to reading and performing cascading deletes. I've read that Maps are the way to go, but that's kind of what I''m having trouble with, especially in terms of reading the data. I'm going to post what I have come up with and I'm hoping that someone can suggest on how I can improve the model or what I can change so that I can access the String values of Days, Workouts, Exercises, and Weight/Repetitions as easily as possible, because the way I have it set out, those values are stored as Keys. Much appreciated!
You can nest up to 100 levels but doesn't mean you should. You can organize your data as a subcollection which is a collection within a specific document. You can query across subcollections with the same collection ID using Collection Group Queries. You can find best practices here
Related
Hello and good morning.
I am working on a side project where I am adding an analytic board to an already existing app. The problem is that now the users table has over 400 columns. My question is that what's a better way of organizing this table such as splintering the table off into separate tables. How do you do that and how do you communicate the tables between the new tables?
Another concern is that If I separate the table will I still be able to save into it through the user model? I have code right now that says:
user.wallet += 100
user.save
If I separate wallet from user and link the two tables will I have to change this code. The reason I'm asking this is that there is a ton of code like this in the app.
Thank you so much if you can help me understanding how to organize a database. As a bonus if there is a book that talks about database organization can you recommend it to me (preferably one that is in rails).
Edit: Is there also a way to do all of this without loosing any data. For example transfer the data to a new column on the new table then destroying the old column.
Please read about:
Database Normalization
You'll get loads of hits when searching for that string and there are many books about database design covering that subject.
It is most likely, that this table of yours lacks normalization, but you have to see yourself!
Just to give an orientation - I would get a little anxious when dealing with a tenth of that number of columns. That saying, I clearly have to stress that there might be well normalized tables with 400 columns as well as sloppily created examples with just 10 columns.
Generally speaking, the probability of dealing with bad designed tables and hence facing trouble simply rises with the number of columns.
So take your time and if you find out, that users table needs normalization next step would indeed be to spread data over several tables. Because that clearly (and most likely even heavily) affects the coding of your application here is where you thoroughly have to balance pros and cons - simply impossible to judge that from far away.
Say, you have substantial problems (e.g. fierce performance problems - you wouldn't post it) that could be eased by normalization there are different approaches of how to split data. Here please read about:
Cardinalities
Usually the new tables are linked by
Foreign Keys
, identical data (like a user id) that appear in multiple tables and that are used to join them, that is.
And finally, yes, you can do that without losing data as the overall amount of information never changes when normalizing.
In case your last question was meant to be technical: There is no problem in reading data from one column and inserting them into a new one (of a new table). That has to happen in a certain order as foreign keys have to be filled before you can use them. See
Referential Integrity
However, quite obvious: Deleting data and dropping columns interferes with the operability of your application. Good planning is due.
This is a design question. I hope that is acceptable here.
Back in the days of yore, I worked on an accounting system that used flat files to store records in a proprietary format. The transaction 'table' stored multiple types of transactions in the format of a fixed header (which held the transaction type amongst other things) and a detail record that varied according to the transaction type.
We did this in C using structs and unions to manage the records.
Once again I find myself working on a finance system, only this time I'm doing it in Rails with PostgreSQL as the target database.
I'm currently considering the design of the transaction system in this new project and I'm wondering how to do this in the best, Rails way.
Do I have multiple tables, one for each transaction type: journals, sales, purchases, etc? (Does this violate DRY?)
Or, do I have a single transaction table that represents the header, and multiple tables for the detail of each type?
If I do it this way, how do associations work? Can an association use a single id to connection to multiple tables?
Or, do I have a single, un-normalized record with every possible field for the complete range of transaction types?
Or... is it possible to overload a table record in the way I did this so many years ago?
(Not really keen to do it this way though.)
Any ideas you have on this will be appreciated.
Option 1 sounds like you'd need a polymorphic association, which is supported by Rails out of the box. Although it works the other way around normally - The usual use-case is along the lines of a comment object that can belong to multiple content types. There's a gist here that may or may not help: gist.github.com/runemadsen/1242485
Although the gist uses a join table on which you can add common fields, which starts to sound like Multiple Table Inheritance, your second choice. This is a good solution. You'll need a gem to make it work with Rails though. Try this one:
github.com/hzamani/active_record-acts_as
Option 3 sounds like single table inheritance which is generally a bad move.
I'm not sure how 4 differs from 2.
I would err on the side of 2: Multiple Table Inheritance. Granted, if a polymorphic association works for you it's nice to be just using Rails native features, but I think you'd find it would get more and more annoying to deal with over time. Simple things like counting all transactions or getting all transactions within a date range would become arduous and fragile. MTI is a pattern created exactly for this kind of situation.
I'm building an application where I will be gathering statistics from a game. Essentially, I will be parsing logs where each line is a game event. There are around 50 different kinds of events, but a lot of them are related. Each event has a specific set of values associated with it, and related events share a lot of these attributes. Overall there are around 50 attributes, but any given event only has around 5-10 attributes.
I would like to use Rails for the backend. Most of the queries will be event type related, meaning that I don't especially care about how two event types relate with each other in any given round, as much as I care about data from a single event type across many rounds. What kind of schema should I be building and what kind of database should I be using?
Given a relational database, I have thought of the following:
Have a flat structure, where there are only a couple of tables, but the events table has as many columns as there are overall event attributes. This would result in a lot of nulls in every row, but it would let me easily access what I need.
Have a table for each event type, among other things. This would let me save space and improve performance, but it seems excessive to have that many tables given that events aren't really seperate 'ideas'.
Group related events together, minimizing both the numbers of tables and number of attributes per table. The problem then becomes the grouping. It is far from clear cut, and it could take a long time to properly establish event supertypes. Also, it doesn't completely solve the problem of there being a fair amount of nils.
It was also suggested that I look into using a NoSQL database, such as MongoDB. It seems very applicable in this case, but I've never used a non-relational database before. It seems like I would still need a lot of different models, even though I wouldn't have tables for each one.
Any ideas?
This feels like a great use case for MongoDB and a very awkward fit for a relational database.
The types of queries you would be making against this data is very key to best schema design but imagine that your documents (in a single collection similar to 1. above) look something like this:
{ "round" : 1,
"eventType": "et1",
"attributeName": "attributeValue",
...
}
You can easily query by round, by eventType, getting back all attributes or just a specified subset, etc.
You don't have to know up front how many attributes you might have, which ones belong with which event types, or even how many event types you have. As you build your prototype/application you will be able to evolve your model as needed.
There is a very large active community of Rails/MongoDB folks and there's a good chance that you can find a lot of developers you can ask questions and a lot of code you can look at as examples.
I would encourage you to try it out, and see if it feels like a good fit. I was going to add some links to help you get started but there are too many of them to choose from!
Since you might have a question about whether to use an object mapper or not so here's a good answer to that.
A good write-up of dealing with dynamic attributes with Ruby and MongoDB is here.
Okay, so I'm putting together a book store with Ruby on Rails. Books are fast moving and varied, so at any point of time there are a small number in the store. Books that have been ordered and shipped must be stored, mainly for the purpose of records.
Hence, I have a situation where a small section of data from a table is going to be very frequently accessed. A much much larger section of it will very rarely accessed at all. My plan is to move books that have been ordered and shipped to a separate table, so that the table of current books is small and very quick to access.
Does this approach make sense? Is there a better way of achieving this?
If I am to use this approach, is there a way of sharing a model between tables in Rails?
I agree with Randy's comment about considering the number of books in the database, and whether or not it's really worth it. Only after you try it, and come back with real performance numbers to consider should you consider optimizing in this way, I believe.
On the other hand, there's plenty of precedent for having the idea of an "archive" table. From a design standpoint, this is totally fine. It's a question of the tradeoff between complexity and performance. But again, only after you try it and see whether or not the performance is acceptable, will you have a solid reason to choose one approach over another.
sorry if the question sounds so weird, but I don' really know how else to put it.
Essentially, my application will a bunch of objects. Each objects has somekind of post/comment structure, the unique thing though is, that it is more or less static, so i figure out it would make no sense to put in every single post and comment into my database, because that would cause more database load? Instead of this, I was thinking about putting the JSON representation of the post with its comments, thus only causing one database access per object. I would then render the JSON object in the controller or view or something. Is this a valid solution?
No!
You loose all ability to query that data at no benefit unless you are at massive scale. The database's job is to pull that stuff out for you efficiently, and if you create the proper indexes and implement the proper caching strategies, you shouldn't have any issues with database load. You want to replace all the goodness of the Rails ORM with your own decidedly less useful version in the interest of a speed gain, waaay before you need it.
What if later you want to do a most popular comments sidebar widget? Or you want to page through the comments, regardless of the post they are associated with, in a table for moderation? What if you want your data to be searchable?
Don't sacrifice your ability to easily query and manipulate the data for premature optimization.
Though it sounds a good idea but I don't think that it will work in the long run thinking of what is going to happen when you have many comments on your posts. You will have to get the long string from the database and then add the new comment to it and then update it in the data. This will be very inefficient compared to just inserting one more comment in the table.
Also, just think what is going to happen, if at some point, you will have to give user the option to update the comment. Getting the particular comment from that long string and then update it will be a nightmare, don't you think?
In general you want to use JSON and the like as a bit of a last resort. Storing JSON in the db makes sense if your information isn't necessarily known ahead of time. It is not a substitute for proper data modelling and is not a win performance-wise.
To give you an idea where I am looking at using it in a project, in LedgerSMB we want to be able to have consultants track additional information on some db objects. Because we don't know what it will be in advance JSON makes a lot of sense. We don't expect to be searching on the data or support searches on the data but if we did that could be arranged using plv8js.