Organise a many to many relationship in MongoDB - ruby-on-rails

I'm building an ecommerce Rails application, and I want to create a relationship between Products and Users.
Users can "favorite" many products (and products can be favorited by users).
Users have a "history" about the products they saw.
In SQL databases, I know I can create, for example, a History table and put the product_id and user_id. And a Favorited table with also product_id and user_id.
But in MongoDB, how can I build this relationships?
I read this blog post: http://blog.markstarkman.com/blog/2011/09/15/mongodb-many-to-many-relationship-data-modeling/ and realized that I can create an array of products inside Users collection, and an array of users inside Products collection. But I don't know how to set what is the favorited product and the history product inside Users collection.
Thanks in advance.
EDIT
Thought: I'm thinking in create two models (ProductFavorited and ProductHistory) inheriting from Product model/collection and use it inside users collection.

The best data model in MongoDB is one that fits your application use.
So the questions to ask are "When are you going to see these favorited Products? How are they displayed?" and "When are you going to see this History? How is it displayed?"
Some possible answers and advice might be:
"A user will be able to click a menu item labeled 'Favorites' and see
a list of Products that they have favorited."
Then it makes sense to store the information you plan to show in a
favorites array on the User document. Or if you expect the User
document to be growing too large, a separate favorites collection
with just a user_id as _id and then just the array of favorites as
the only other element in the document.
Or:
"A user will go to a Product page and see a list of other users that have favorited that Product."
Then it makes sense to store it the other way with all of the users that favorited the product in the Product document. Or if you think the Product document will grow too large then in a separate collection with product_id as the _id and the favorited_users as an array which is the only other element in the document.
The thing to always keep in mind is how the data will be used in your application.
Information about Data Model in MongoDB.

Related

Categories assigned to user model - rails

Within my rails app I have two models. A User model and a Book model. A user uploads and has many books.
I'm trying to add 10 predefined categories to the user model, so that a user assigns as many of the 10 categories to themselves as they wish. For example, if i'm a user that uploads a several books, and the categories I chose in my user settings are "fiction" and "science"
If another user chooses "fiction", "science", "history" as their categories, I want to be able to show them all books uploaded by users that are under these three categories including all the books I uploaded since I am under the categories of "fiction" and "science"
What is the best way to implement this? I was thinking of using the acts-as-taggable-on gem but maybe this is too heavy weight and necessary. Should I just add a string column to my user model where each category is separated by a comma, so that I can split them up into an array and do queries with Active Record?
Obviously you could create your own solution for the problem but ActsAsTaggableOn is a very good solution for it. It is not such a heavy weight as other gems.
Bonus: You can go back any time if it becomes too heavy for your application. Which I doubt.

Relational Database Design (E-Commence) - Core Data

In my e-commence app (for café/restaurants) I currently have the following database structure.
The cart is the shopping cart, in which you can add products, a temporary place before the products/an order is sent to the server. The ProductCart is a line item, many products (could be the same) with the different quantities, sizes, frying levels etc. When a order is sent, the cart is cleared and the products in the cart is transfered to the ProductOrder entity (an Order).
I now want to extend this further, with the ability of the products having ingredients and this is where it gets tricky and too complex for my head and database skills :-). As well as the (same) products can have different sizes and frying levels (hence the line item) a product should have the ability to have many different ingredients (add ons) for example a pizza, where you could choose the topping. This is what I have tried so far:
But I am not sure if this is the right structure or way to do it?
This is my suggestion.
Remove ProductOrder and Order entities. They are the same as ProductCart and Cart.
Now ProductCart should have an attribute like synchronized that is 1 or 0 based if it has been sent to server or not.
Through this you should simplify a lot your model. About Ingredient… entities they seem ok to me.
There is something fundamental you have not grasped about Core Data. Your ProductOrder entity is essentially a join table. This is completely unnecessary if you are not tracking additional attributes in this table.
Instead, you should have a many-to-many relationship between Order and Product.
It might seem that ProductCart satisfies my condition above that in this case a join table makes sense. But no - you should simply add the orders to your cart and track all the information in the Order entity.

Simple Ruby on Rails database design

For practice I'm writing a shopping website where we have tables User and Item. A user obviously has_many items (when they are added to their basket), but the item, it belongs_to a User, even though many users will have the same item in their basket?
Furthermore, what if I want a list of items a user has added to their basket, but also a list of items they have viewed (for making suggestions based on searches), would it be better to have some 'through' tables: Basket and Viewed?
When you have this many-to-many relationships, you can use the HABTM schema:
Class User...
has_and_belongs_to_many :items
However, most of the time webshops use orderlines to keep up with items that users are purchasing. This means that an 'user' 'has_many' 'orderlines', an 'item' 'has_many' 'orderlines', an 'orderline' 'belongs_to' an 'user' and to an 'item'.
And maybe your orderlines will just be copies of items, and won't have a direct link because you don't want to alter the orderline after they have been processed. It really depends on the focus of your shop which scheme suits your needs.
Try to find some examples on the web and think about how you want to handle items, orders and baskets.
I'm used to separate things that are not the same, even if the relationship is one-to-one. So first of all I would recommend users from baskets (1:1-relationship).
After that a basket contains many items and items can be in multiple baskets (m:n-relationship). Make sure, that maybe a user likes to buy the same item multiple times.
views can be realised as a linking table between users and items: users have many views and items have many views, but one view is always linked to exactly one user and one item.

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.

deep nesting or different collection mongodb?

I am trying to work out the best way to store my daat using mongodb and mongomapper.
I have category and each category can be described by many attributes so length in mm, weight in kg etc.
I want each user to be able to create their own attributes to descibe a category of products.
So forexample:
user A wants to store his category "cars" with number of wheels and length of car in mm
user B wants to store his category "cars" with number of wheels and length in mm and weight in kg.
The categories are the same for everyone but attributes can be different.
Should i be storing this as category collection then each cateogry contains and array of users each containing a hash of attribute anmes and units ?
Or should i be breaking this up into multiple collections somehow ?
Or is there a better way anyone can think of ?
Is it a problem with deep nesting ?
thanks alot in advancfe for help and advice.
rick
Lets start with the easy answer. Store the attributes as fields in the items document. This is why one uses a schema-less data store.
Now, about which witch attributes to put with which item. Short answer: Any of the ways you describe will work; all have some trade-offs in terms of efficiency.
I think your model goes like this:
There is a collection users
There are many collections of items called categories
each item is a member of a category
each user has many items
every item in a category has many potential attributes depending on the user
some users will share attributes
I would have the following collections: users, *categories(e.g. cars, boats, houses, etc...), attributes.
The attributes collection would list a category(e.g. cars), and attribute of items in that category (e.g. fuel mileage), and a list of user_ids who use that attribute.

Resources