I have three main mySQL tables:
users
tags
news_articles
I also have many to many tables to connect them as needed.
I want to grab all the articles that share the same tags as users so I can personalise their experience.
(example): say a user has tags for "Trump" or "Brexit" I want to grab all the news articles that also have Trump or Brexit.
I could grab the whole data pool and make calculations but that might get unnecessarily server intensive so is there a way of doing it through Eloquent?
Also is Eloquent capable of tallying the user tags to determine which tags the user is most interested in before grabbing the articles or would that need a workaround after?
Thanks in advance.
Christophvh's response did work for me in the end. After some more time with Eloquent I found plenty more ways of doing this.
A way I would go about this now for anyone who happens to be stuck:
By creating a tags method in my User and Article models to return all related tags I can then do the following.
$userTags = $user->tags()->pluck('name')->get()->toArray();
$articles = Article::whereHas('tags', function($tag) use ($userTags) {
$tag->where('name', $userTags)->get();
})->get();
The above code should:
Get only the name field of all tags belonging to a user and store them in an array.
Grab all articles where their related tags name field contain any tag in the $userTags variable
To create a priority tags list I would just need to run array_count_values($userTags) and order it by the returned values, then pass the new ordered $userTags array into the Eloquent query.
Related
I am currently developing a system to filter and display data that is used via Eloquent and saved to the database in the following way:
Catalog -(1)---(n)-> Product -(1)---(n)-> Group -(n)---(n)-> Part
Product -(n)---(n)-> Provider
I'm eager loading these models completely and then display their attributes in my view as a table, the columns I base on user settings. Now I'm trying to add a way to order (and search through) these columns, but I can't seem to figure out any way to be able to order the whole result (Catalog is ultimately the 'master' collection) by any nested attributes.
For parts and providers (n:n relationships) I only need to be able to order the result by either the first or the last one's attributes.
Can anyone help me out here? I tried joins, but I can't figure out how to join both the first element and the last element for those two models and somehow distinguish them.
In my users table i have column TAGS, that is serialized array, ex. serialize(['fun','promo'])
Then in my Campaign table I have also tags column similar to column in users table.
My question is how to display to user only those campaigns that have at least one tag same as in campaign tags. And if campaign has no tags display to every user no metter which tags they have.
And if user has no tags set display every campaign to him.
How to query that?
$campaign = Campaign::where('tags', $user->tags);
This won't work I know because it has to search in serialized array.
But how can I do that query?
You should normalize the data by storing the tag relationships in separate tables:
campaign_tag
-campaign_id
-tag_id
tag_user
-tag_id
-user_id
The Laravel documentation (https://laravel.com/docs/5.2/eloquent-relationships#many-to-many) has good examples of how to then query/filter the data.
I'm super new to CakePHP. I've searched everywhere for this but I can't seem to be able to get it right, or find any sort of orientation. I still don't get how the whole HABTM thing works and I'm expecting to learn more from this.
I'm trying to do a Twitter-like system, with users and followers, and posts (tweets) and shares (retweets). I've set up the users and posts models, and join tables for followers (between users and users) and shares (between users and posts). How should I set up my model associations? I've been trying several ways but I'm not certain on whether I'm doing it right or not.
And the other question is, what would be the proper find query to get all posts by the people I follow, plus the posts they've shared, without getting all the unnecessary data like user info and such, just the posts in one array? Is it possible with find in one query, or should I do several and then merge the arrays? Plus, it would be extremely useful to understand how to properly filter and limit this rather complex query (obtaining a "posts timeline" between certain date ranges, limit the posts to a certain amount, or both).
I know my question is a little bit silly, but I swear I've done a lot of research and I can't seem to be able to get it right. So any help, especially with the query part, would be greatly appreciated.
Thanks!
So these would be some weird relationships. I'm feeling you should have the following tables:
Users (with alias Followers) hasMany tweets
Posts belongsTo Users
UsersFollowers (A HABTM table)
To make this work on just three tables, Posts would need to be a threaded table. In essence, if a person retweets (shares) a post a new record is created with the id of the original post in the new posts parent_id column. Then when the record was called the model could pull up the additional data and include it in the feed.
The alias aspect of Users allows for the follower part to be done in just one table. To find followers of a person, search with one key of the table (follower_id) and to find the people a person follows just search with the other key (users_id).
As for the second part of your question, finds should be pretty easy in this setup, but you might want to read up on Containable and threaded queries. You could include timestamp columns in the tables so you could later do a search by date feature (or a post timeline).
I'm trying to create a small Web App to categorize certain type of YouTube videos, when users submits a video they will choose what categories this video falls under and they will tag it with ready-made tags, for example:
Video one - Category: Ad - Tags: cute, funny, has animal in it.
I'm trying to sketch my Database for that (I'm using MySQL), so far I have two ideas.
Idea 1:
Table Videos with ID and Category columns, another table Tags with ID and Tag columns while Videos.ID and Tags.ID are linked together. So when the user tries to filter search results by tags, the query will have more conditions (AND Tag = 'something' AND Tag = 'other thing').
Idea 2:
One table Videos with Category and Tags columns, tags are stored as a string separated by commas, when the user tries to filter search results by tags, the query will more conditions (AND Tags LIKE '%something%' AND Tags LIKE '% other thing%).
So the question is: Is there any better method? I already think that the 1st one is wasteful (Each video might have up to 40 ready-made tags) and the 2nd one is clumsy. If not, which one do you think is better?
Creating a additional table linking video id and tag id together is the correct solution. Filtering is done by creating additional INNER JOIN conditions. A comma separated list just won't do - it drastically limits your selection and query possibilities.
Idea 1 looks good. Creating a separate table for storing tags helps in selection.
I would like to have categories, and rankings for my content and users respectively, and I am not sure how to go about implementing this using CakePHP conventions?
Do I need to create a model?
That depends entirely on what these categories are supposed to do and not do. You could simply define a number of constants that you use for categorizing stuff. But, are categories...
subject to change? Do you want to add more eventually?
editable? May you want to change their names?
nested?
supposed to have more attributes than just their id? Names, descriptions?
If you answered Yes to any of the above, you'll want to store them as data in the database. This is independent of Cake, it's just sane data modeling. For Cake that means you'll need to create a model. The same goes for ratings.
So you'll have these tables:
users
hasMany ratings
categories
hasMany contents
contents
belongsTo categories
hasMany ratings
ratings
belongsTo users (polymorphic)
belongsTo contents (polymorphic)
You may want to separate user ratings and content ratings into two tables instead of using a combined polymorphic table (which just means that you have an extra column keeping track of whether a rating is for a user or for content).
i guess you are looking for something like this IF you dont want to use a model:
http://www.dereuromark.de/2010/06/24/static-enums-or-semihardcoded-attributes/
one possible approach to use "enums" for things that maybe only have 1-5 states.
if you have more than 10 or you want to be able to dynamically modify them (label, active/inactive) you will need a separate table and model relation.