I build a Rails 4 application with a Redis Datastore.
The model has some complex objects to store products and some associations to them.
This application is used by up to 50 customers.
Every customer has his own products (up to 2000 products)
Now... I don´t wanna mix up the products in one redis object.
Is it a good idea to create an object per customer so redis does not have one big product object for all customers?
I think about something like a prefix on a customer specific token.
The object for an customer specific product object can called like 'amazon_products'
What do you think? Any suggestions?
If you want to do operations on these products based on the customer they belong to then yes, I would create one object per customer. I would also use a prefix like pr:<user-id> (ie. pr:123 would contain all the objects for customer with id 123).
However it depends on the ways you will ask for the data and the operations that you will perform on them.
Related
I have three models, let's call them Product, TemplateProduct and ReadyProduct. There is only one table for these, the products table, and both TemplateProduct and ReadyProduct inherit from the Product model. There is a has_many/belongs_to association between TemplateProduct and ReadyProduct. Templates are used to lay out general characteristics for products, Readys are used to customize the products and what are actually made available for view by the customer. Each TemplateProduct has an id and each ReadyProduct has a template_product_id which ties to it's template.
The project is built using Rails 5.
What I want to be able to do is to gather a list of TemplateProducts, then get a count of each templates associated ReadyProducts and do so in such a way that won't hammer the database. I understand ActiveRecord associations but my SQL is weak and I have only a limited understanding of joins. I can gather a list of TemplateProducts with a simple Product.where(conditions) but I don't know what to once I have this. For the sake of flexability sake I want to be able to base my ReadyProduct count off of this initial collection as sometimes I'll need the additional count and sometimes I won't. I'm sure there must be a simple way to do this but I haven't found a solution.
If you just need a mapping of TemplateProduct ids to ReadyProduct counts, then all you need is:
TemplateProduct.joins(:ready_products).group(:id).count
If you want TemplateProduct instances with a baked in ReadyProduct count, then you'll need this instead:
tps = TemplateProduct.joins(:ready_products).select('products.*, COUNT(ready_products_products.id) ready_product_count').group(:id)
tps.first.ready_product_count
#=> 6
ready_products_products gets defined by Rails, it prefixes the actual table name (products) with the model name's "table form" (pluralized, snake case, lower case, ready_products), joined with an underscore.
I want to create an application for enabling the users to book the computers in a laboratory if they want to use it from a specific time to time.The users can book the computers for their next 15 days. So,how should I design the database for this application.
Start by defining what your entities and attibutes will be. It's better if you can do a Conceptual Design first.
Than you design it logically.
For example, your entities might be:
USERS, COMPUTERS, RESERVATIONS.
Your attributes might be:
USERS (SomeUniquePersonalIDnumber, Name, Surname, Email*, PhoneNumber*)
PrimaryKey in bold. With asterisk *Optional
COMPUTERS (UniqueComputerSerialNumber, NumberOfComputerInLab)
RESERVATIONS (AutoincrementNumber, UserPK, ComputerPK, DateOfReservation, TimeFrom, TimeTill)
PrimaryKey composed of the three attibutes making it unique. Same user might reserve the same computer over time but the AutoincrementNumber field will make the composite PK unique.
RESERVATIONS(UserPK) referencing USER(SomeUniquePersonalIDnumber)
RESERVATIONS(ComputerPK) referencing COMPUTERS(UniqueComputerSerialNumber)
Define what type of fields will those attributes be
(Integer/Varchar/...) based on the querying language you will want
to use.
Translate all of above into commands to create the database, the
tables etc.
Just pick a piece of paper and start with normalization https://en.wikipedia.org/wiki/Database_normalization.
If I look for entities in your question I see the following entities:
user
computer
booking
Then you need to figure out what properties belong to those entities and the relation between them. You can create an ERD if you like and start creating Ruby on Rails models.
In Ruby on Rails if you generate a model the model has a created_at datetime field by default. I think you can use that to figure out the specific time and check if 15 days are past since this booking is created.
I'm building a Ruby on Rails App for a business and will be utilizing an ActiveRecord database. My question really has to do with Database Architecture and really the best way I should organize all the different tables and models within my app. So the App I'm building is going to have a database of orders for an ECommerce Business that sells products through 2 different channels, a subscription service where they pick the products and sell it for a fixed monthly fee and a traditional ECommerce channel, where customers pay for their products directly. So essentially while all of these would be classified as the Order model, there are two types of Orders: Subscription Order and Regular Order.
So initially I thought I would classify all this activity in my Orders Table and include a field 'Type' that would indicate whether it is a subscription order or a regular order. My issue is that there are a bunch of fields that I would need that would be specific to each type. For instance, transaction_id, batch_id and sub_id are all fields that would only be present if that order type was a subscription, and conversely would be absent if the order type was regular.
My question is, would it be in my best interest to just create two separate tables, one for subscription orders and one for regular orders? Or is there a way that fields could only appear conditional on what the Type field is? I would hate to see so many Nil values, for instance, if the order type was a regular order.
Sorry this question isn't as technical as it is just pertaining to best practice and organization.
Thanks,
Sunny
What you've described is a pattern called Single Table Inheritance — aka, having one table store data for different types of objects with different behavior.
Generally, people will tell you not to do it, since it leads to a lot of empty fields in your database which will hurt performance long term. It also just looks gross.
You should probably instead store the data in separate tables. If you want to get fancy, you can try to implement Class Table Inheritance, in which there are actually separate but connected table for each of the child classes. This isn't supported natively by ActiveRecord. This gem and this gem might be able to help you, but I've never used either, so I can't give you a firm recommendation.
I would keep all of my orders in one table. You could create a second table for "subscription order information" that would only contain the columns transaction_id, batch_id and sub_id as well as a primary key to link it back to the main orders table. You would still want to include an order type column in the main database though to make it a little easier when debugging.
Assuming you're using Postgres, I might lean towards an Hstore for that.
Some reading:
http://www.devmynd.com/blog/2013-3-single-table-inheritance-hstore-lovely-combination
https://github.com/devmynd/hstore_accessor
Make an integer column called order_type.
In the model do:
SUBSCRIPTION = 0
ONLINE = 1
...
It'll query better than strings and whenever you want to call one you do Order:SUBSCRIPTION.
Make two+ other tables with a foreign key equal to whatever the ID of the corresponding row in orders.
Now you can keep all shared data in the orders table, for easy querying, and all unique data in the other tables so you don't have bloated models.
I'm trying to understand how to use the Redis-Objects gem.
My goal is to Count the number of Purchase model instances by customer_id. For example, a customer loads a page and I would like to see the number of purchases by that Customer. To be clear the Purchase model has a customer_id column. Because of the volume of hits, I would like to use redis to relieve pressure on my server.
Does one use set to accomplish this task? How does one use the redis-objects gem to accomplish this task?
when working with Redis, it is best to model your data according to your access patterns. In other words, de-normalize your data.
Here is what I would do :
Customer and Purchase objects are stored in a Hash.
Customer hash should have a field total_purchases
Every time a customer purchases something, use HINCRBY to increment the total_purchases field
On page load, simply read the value of total_purchases
Hi iam new in dynamo db and, with my knowledge its a non relational db ie we cant join the tables. My doubt is how we design the table structure. Please clarify with following example.
I have a following tables
1) users - user_id, username, password, email, phone number, role
2) roles - id, name [ie admin, supervisor, ect..]
a) My first doubt is we have any provision to set auto increment for user_id fields ?
b) Is this correct way of setting primary key as user_id?
c) Is this is the correct method to store user role in dynamo db? ie a roles table contains id and title and store role id in user table?
e) Is this possible to retrieve two tables data along with each user? Am using rails 3 and aws-sdk gem
If anybody reply it will be very helpful for me like a new dynamodb user
Typically with nosql style databases you would provide the unique identifier, rather than having an auto increment PK field do that for you. This usually would mean that you would have a GUID be the key for each User record.
As far as the user roles, there are many ways to accomplish this and each has benefits and problems:
One simple way would be to add a "Role" attribute to the Users table and have one entry per role for that user. Then you could grab the User and you would have all the roles in one query. DynamoDB allows attributes to have multiple values, so one attribute can have one value per role.
If you need to be able to query users in a particular role (ie. "Give me all the Users who are Supervisors") then you will be doing a table scan in DynamoDB, which can be an expensive operation. But, if your number of users is reasonably small, and if the need to do this kind of lookup is infrequent, this still may be acceptable for your application.
If you really need to do this expensive type of lookup often, then you will need to create a new table something like "RolesWithUsers" having one record per Role, with the userIds of the users in the role record. For most applications I'd advise against doing something like this, because now you have two tables representing one fact: what role does a particular user have. So, delete or update needs to be done in two places each time. Not impossible to do, but it takes more vigilance and testing to be sure your application doesn't get wrong data. The other disadvantage of this approach is that you need two queries to get the information, which may be more expensive than the table scan, again, depending on the quantity of records.
Another option that makes sense for this specific use case would be to use SimpleDb. It has better querying capability (all attributes are indexed by default) and the single table with roles as multi-valued attribute is going to be a much better solution than DynamoDB in this case.
Hope this helps!
We have a similar situation and we simply use two DBs, a relational and a NoSQL (Dynamo). For a "User" object, everything that is tied to other things, such as roles, projects, skills, etc, that goes in relational, and everything about the user (attributes, etc) goes in Dynamo. If we need to add new attributes to the user, that is fine, since NoSQL doesn't care about those attributes. The rule of thumb is if we only need something on that object page (that is, we don't need to associate with other objects), then we put in Dynamo. Otherwise, it goes in relational.
Using a table scan on the NoSQL DB is not really an option after you cross even a small threshold (up to that point, you can just use an in memory DB anyway).