Mongoid - Using object.in(map) as a workaround for has_many :through? - mongoid

I'm converting an AR app into mongoid to learn, and was relying heavily on has_many :through.
class User
has_many comments
has_many posts, through: :comments
has_many categories, through :posts
This worked for things like retrieving titles of the categories the user posts in most frequently: user.categories.each
But with Mongoid not allowing joins, I stumbled across someone elses code for another problem not related to joins, but it seems like it is close to a substitute?
def posts
Posts.in(id: comments.map(&:post_id))
end
I was surprised to see it worked further as well, to the second 'join'
def categories
Category.in(id: user.posts.map(&:category_id)
end
It works for my current problem, I just have to call user.categories.each do and I have the same functionality as I did with the chained :throughs in AR.
But is this an incorrect way to think about using mongoid? It definitely queries the server multiple times... I've also been learning about denormalizing the data as needed, in this case putting category_ids field directly into users document, but manually updating the data with callbacks seems to get messy, and I haven't been happy with mongoid_denormalize or mongoid_alize gems.
This seems to be a recurring problem for my thought process. For example I'd like to be able to show categories in order of posts.comments.count, or or users who are active in the most popular categoires, or friends of users ordered by those that have the most comments in their posts...
When trying to order_by by second or even third level associations, is there a better way?

Related

Multiple datasources for one model in CakePHP

I have a very interesting problem in relation to CakePHP. I have a client that is currently selling products on eBay, and wants to start selling products on their own website as well. There would, then, be two separate sales avenues: (1) eBay, and (2) website.
However, they do want to have a seamless website experience for their customers. Basically, they want their current eBay sites to be categories within their current website, and their current eBay auction items to be searchable on their website.
A simple CakePHP website would have two tables: products and categories, with the simple table relation of "products belongsTo categories" and "categories hasMany products". How would I then add in the eBay categories and products? Basically, I want the http://site/products/index to return a list of ALL products, both in the products table and on eBay. I want http://site/categories/index to return a list of all defined categories in the categories table plus the categories items are listed in on eBay.
eBay has a very good pretty much real-time request query API, so I've been thinking about an option to do this, but am wondering if there is a better way... I don't think this option would work very well with PaginatorComponent...
Method:
(1) In beforeFind, capture the request parameters and save to a persistent variable
(2) In afterFind, make a request to the eBay API based on the request parameters, then manually add the results to the $results array.
Again, I think this would work for basic find operations, but I'm not sure this would work with pagination because I'm not sure how to deal with, say, a 20 item page limit (i.e. How do I deal with a page 2 when only 18 items from the database were on page 1, and now on page 2 I need to start at 19 instead of 21 from the database?)
Is there a CakePHP syntax that I'm overlooking here, or do I just start working on coding for all of these eventualities?
I'm coding on a CakePHP 2.6.0 platform.
Thanks so much for your help!
One possible approach would be to read all the products from each datasource, sort them in memory and paginate from there. The number of products would of course play a major role here.
A second one, if the number of products does not change too often, would involve a background process to retrieve their ID, and the most essential data, from eBay and write them in the common Product table, flagging the rows created.
Then Paginator can then show your results, but other fast-changing data can be retrieved on-the-fly from eBay for the flagged products while composing the page.

Database design for like/love relations

I know this might have been asked quite a few times, however I can not find any suitable solution for my problem.
I am implementing database where I have users and articles.
Now the article can be either liked or loved by any of the user.
And here comes the problem, I have to return json that contains list of all articles extended by two fields, liked and loved, because queries are gonna be connected to users.
So liked and loved might be true or false.
I thought about creating two different tables Liked & Loved where I would keep article_id - user_id and if that record exists that means user liked/loved particular article. However I am not quite sure if thats the correct way, nor I have any idea how would I build such query.
If it is important I am using postgresql together with ormlite.
Thanks for any ideas.
If I have understand your question you are basically describing an M-N relationship. A user likes/loves N articles and an article is liked/loved by M users. Such relationships are implemented via a third table that stores the association of users and articles.
You could create a table UserPreferences that links user_id and article_id and has extra columns to indicate if he liked/loved the article.
I can't tell you more about the schema since I don't know if you have other degrees about the preferences (hated, indifferent, confused etc)

CakePHP makes a join between two models, but not between two others

I have four very simple models. Offer, Employer, Employee and Response.
Offer hasOne Employer
Employer hasMany Offer
Response hasOne Employee
Employee hasMany Offer
And now when I make a find() on Offer, it nicely makes a JOIN query and returns Employer details.
But when I make a find() on Response, it doesn't attempt to retrieve Employee's data.
I reviewed the code many times, stripped the models off of any additional properties etc., and still nothing. Those models are now nearly identical, their SQL tables too, but Response behaves like it has no relation to Employee defined.
Any pitfall with this that I might be trapped in? I'm ready to report this as a bug at this moment.
I can post complete (which are short, anyway) model definitions here if it helps anything.
Check the class of your model instances
I.e.
debug(get_class($this->Response));
If it outputs AppModel - the reason your code doesn't appear to be being used, is because: it isn't being used. That being the case, check for typos in the filename/location of your model files - as CakePHP will silently use an AppModel instance if your model files don't exist.

How do variable Model names work in CakePHP tables?

Looking at the tables (aros, acos) generated by the ACL component and for example the Favorites plugin by CakeDC I see the favorites table with the fields Favorite.user_id, Favorite.model and Favorite.foreign_key.
The last two combined are replacing the good old Favorite.post_id (presuming model has the value 'Post'). It is in a way a HABTM pivot table with a dynamic modelname on one side.
I can see the general and useful idea here but would like to know more about the application of it.
My question(s):
Does this pattern have a name?
How does this work code-wise? I can see the abstract principle, but what kind of model-code is needed to make this work? Does it involve a patchwork of queries, or does this allow for a smooth one-query implementention? E.g.: I'd like to fetch all marked-as-favorite Posts in the system and their related Users in one go.
And does this work both ways? (querying from both the Post model as well as the User model)
I'd like to work towards an abstraction where I put a behavior in place to take care of this pattern.
I did look into the CakeDC code but could not figure out the principle. It's a little too cryptic for my current knowledge. Hence my question here.
kind regards,
Bart
Does this pattern have a name?
http://en.wikipedia.org/wiki/Junction_table aka Join Table.
How does this work code-wise? I can see the abstract principle, but
what kind of model-code is needed to make this work? Does it involve a
patchwork of queries, or does this allow for a smooth one-query
implementention? E.g.: I'd like to fetch all marked-as-favorite Posts
in the system and their related Users in one go.
It is just a regular join table, that's all. You can simply rely on what CakePHP is building up when using the HABTM assocs or refine your query by using joins. See http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables.
The model field is not needed in that "pattern" but allows you to have just one join table that can be used for many different tables/models. For example instead of having tags and users and posts associated by tags_posts and tags_users we simply use the same table and filter by the model field.
And does this work both ways? (querying from both the Post model as
well as the User model)
Yes if you set the HABTM association up in both models.
Thanks for using our plugins. ;)

Database Design for ECommerce project (Should I use EAV Approach)

I am about to deign my first E-Commerce Database.
What i have find out in most E-Commerce websites is that these sites have Category, then SubCategory and then again SubCategory and so on. And the depth of SubCategory is not fixed means One Category have six nested Sub Category while some other have different
Now All the products have attributes associated with it.
Now my question is are these websites keep on adding tables for nested sub categories and keep on adding columns for the attributes in the database
OR
They apply something called as "EAV" model (if i am right) to solve this problem or they keep on adding columns and or tables and also keep on updated the WebPages as on many sites i have found there is now a new category.
(If they use EAV model then the website performance is impacted isnt it..)
Since this is my first ECommerce project please provide some valuable suggestions of yours.
Thanks,
Any help is appreciated.
What you need is a combination of EAV for product features and nested sets for product categories.
While I certainly agree that EAV is almost always a bad choice, one application where EAV is the perfect choice is for handling product attributes in an online catalog.
Think about how websites show product attributes... The attributes of products are always shown as a vertical list with two columns: "Attribute" | "Value". Sometimes these lists show side-by-side comparisons of multiple products. EAV works perfectly for doing this kind of thing. The things that make EAV meaningless and inefficient for most applications are exactly what makes EAV meaningful and efficient for product attributes in an online catalog.
One of the reasons why everyone always says "EAV is EVIL!" is that the attributes in EAV are "meaningless" insofar as the column name (i.e. meaning of the attribute) is table-driven and is therefore not defined by the schema. The whole point of schemas is to give your model meaning so this point is well taken. However in the case of an online product catalog, the meaning of product attributes is really unimportant to the system, itself. The only reason your catalog system cares about product attributes is to dump them in a list or possibly in a product comparison matrix. Therefore EAV is doesn't happen to be evil in this particular case.
For product categories, you want a nested set model, as I described in the answer to this question. Nested sets give you very quick retrieval along with the ability to traverse multiple levels of an unbalanced hierarchy at the expense of some precalculation effort at edit time.

Resources