Discussion:
Like Posts - Store Data in DB, User_Meta or Post_Meta
BenderisGreat
2013-11-11 18:01:36 UTC
Permalink
What would be the best option for storing which posts a user likes? They
click a like button, and it can be stored in the post_meta, or the
user_meta, or a sep db table. It seems to be that storing in the post_meta
would make the most sense, but I wanted to ask before moving ahead.



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
chriscct7
2013-11-11 18:12:49 UTC
Permalink
It depends why you are storing it. If you store it in user_meta, to say make
a feature that lets users find the posts they favorited, you can get all the
posts in a single query to the user_meta, versus querying all posts that
have a meta_key with a meta_value that contains a given user->ID. Now if you
are making a feature where you want to know who favorited a post, store all
the user->Id's in a post_meta. Then for a given post you can query a single
post_meta versus querying all users with a given meta_key with a meta_value
that contains a given post->ID





--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42770.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
Gregory Lancaster
2013-11-11 18:14:28 UTC
Permalink
The idea was actually to do both. Show on a single post the number of
people who liked it, and on mouseover list the user IDs of the folks who
did. Then on their profile page have a "this user liked 6 posts" or
whatever it may be, and have that be clickable to open a new page with the
lists of posts they liked.
Post by chriscct7
It depends why you are storing it. If you store it in user_meta, to say make
a feature that lets users find the posts they favorited, you can get all the
posts in a single query to the user_meta, versus querying all posts that
have a meta_key with a meta_value that contains a given user->ID. Now if you
are making a feature where you want to know who favorited a post, store all
the user->Id's in a post_meta. Then for a given post you can query a single
post_meta versus querying all users with a given meta_key with a meta_value
that contains a given post->ID
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42770.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
chriscct7
2013-11-11 18:16:52 UTC
Permalink
Sounds like the best thing would be to store it in both places. Saves two
potentially expensive query's as your site scales up.

-Chris



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
Gregory Lancaster
2013-11-11 18:18:46 UTC
Permalink
Alright that is what I thought might be best, but I often get awesome
suggestions here for simplifying code I wrote so I had to ask. Thanks
Post by chriscct7
Sounds like the best thing would be to store it in both places. Saves two
potentially expensive query's as your site scales up.
-Chris
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Andrew Bartel
2013-11-11 18:42:13 UTC
Permalink
I have to respectfully disagree with Chris, I wouldn't store it in both,
storing duplicate data in general is a dangerous path to go down. It might
make sense at this moment, but say you want to add a feature six months
from now where someone can unlike a page from their profile and you only
write code to update the post_meta table, forgetting to update the
user_meta table. Or maybe you bring another developer on and forget to
document that in the comments of every place that the updates can take
place.

Figure out which one is going to be the more expensive set or queries
(probably retrieving a list of users that have liked a post if you have a
large site) and store it there. Cache the results for the other one if you
have to. You shouldn't hit a performance bottleneck for quite a while
though if you use built in WP functions.

-Andrew


On Mon, Nov 11, 2013 at 10:18 AM, Gregory Lancaster <
Post by Gregory Lancaster
Alright that is what I thought might be best, but I often get awesome
suggestions here for simplifying code I wrote so I had to ask. Thanks
Post by chriscct7
Sounds like the best thing would be to store it in both places. Saves two
potentially expensive query's as your site scales up.
-Chris
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Post by chriscct7
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Gregory Lancaster
2013-11-11 18:44:55 UTC
Permalink
How would I cache the results? I am still learning php so forgive the
(probably stupid) quesiton. But I wrote a function the other day, and if I
could cache one DB call and call that in another function that would have
saved me two different sql calls.
Post by Andrew Bartel
I have to respectfully disagree with Chris, I wouldn't store it in both,
storing duplicate data in general is a dangerous path to go down. It might
make sense at this moment, but say you want to add a feature six months
from now where someone can unlike a page from their profile and you only
write code to update the post_meta table, forgetting to update the
user_meta table. Or maybe you bring another developer on and forget to
document that in the comments of every place that the updates can take
place.
Figure out which one is going to be the more expensive set or queries
(probably retrieving a list of users that have liked a post if you have a
large site) and store it there. Cache the results for the other one if you
have to. You shouldn't hit a performance bottleneck for quite a while
though if you use built in WP functions.
-Andrew
On Mon, Nov 11, 2013 at 10:18 AM, Gregory Lancaster <
Post by Gregory Lancaster
Alright that is what I thought might be best, but I often get awesome
suggestions here for simplifying code I wrote so I had to ask. Thanks
Post by chriscct7
Sounds like the best thing would be to store it in both places. Saves
two
Post by Gregory Lancaster
Post by chriscct7
potentially expensive query's as your site scales up.
-Chris
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Post by Gregory Lancaster
Post by chriscct7
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
BenderisGreat
2013-11-13 14:34:30 UTC
Permalink
What Andrew said about duplicate data being dangerous got me thinking, and I
am now wondering if there is an more efficient way to store some
information. I have an activity feed that updates whenever someone does
something, and it stores the time it occurred, the action_name, the user_id,
and an additional data field I included so I could easily echo out
additional information.

For example, someone likes a post. That gets stored in the db table
'post_likes' along with the user_id, post_id, and datetime. At the same
time, an activity_tracker() function updates the table with the user_id,
activity_id, datetime, and and data_field that stores additional information
(for this example, lets say its the post_id).

Then on the page I call the activity_message() function which queries the
activity_tracker() and displays their activity. The extra data field I
mentioned (post_id) is used to echo out the name of the post a user liked.

Is there a smarter way to do this? Maybe a table join to reduce the number
of sql queries, and stop the need to store additional (redundant) data just
so it can be echoed out? If I don't store duplicate information in the
tables, there is no way for me to associate the post_id that was liked with
the activity_type, user_id and datetime.



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42817.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
Otto
2013-11-11 18:43:38 UTC
Permalink
We implement plugin favorites on WordPress.org in a similar manner.

The plugin directory is a bbPress installation, so plugin entries are
"topics". When a user favorites a plugin, the ID of that topic is saved to
their usermeta, and the ID of that user is saved to the topicmeta.

The question is one of querying. We want to be able to show a user's
favorite plugins (so, get the usermeta, then get those topics), and we
potentially want to be able to show what users favorited a plugin as well
(so, get the topicmeta, then show those users). While we're not actually
doing the latter at the moment, it's a potential case, so there it is.
Reviews are even more complex, since they integrate three things: users, a
plugin or theme, and a post in the support forums.

The problem you'll run into is one of making sure the data is synced across
the two. What happens when your process craps out after adding the
usermeta, but before adding the postmeta? This isn't a problem on a small
scale, but when you build to large scale, it will happen eventually.

In the long run, I think that we'll end up using a custom table for this,
in order to keep everything in a single location and to be able to query by
either case. Meta isn't a great fit for connecting two entirely disparate
sets of data together with a many-to-many relationship. There really is no
proper many-to-many metaphor in WordPress, as such. You can do it with
taxonomy, but that way lies madness. ;)

-Otto


-Otto
Post by chriscct7
Sounds like the best thing would be to store it in both places. Saves two
potentially expensive query's as your site scales up.
-Chris
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Gregory Lancaster
2013-11-11 18:47:15 UTC
Permalink
Awesome answer, I was steering away from storing in a custom table because
people tell me OFTEN that I should always try to make use of the built in
wordpress meta fields available. But this makes sense.
Post by Otto
We implement plugin favorites on WordPress.org in a similar manner.
The plugin directory is a bbPress installation, so plugin entries are
"topics". When a user favorites a plugin, the ID of that topic is saved to
their usermeta, and the ID of that user is saved to the topicmeta.
The question is one of querying. We want to be able to show a user's
favorite plugins (so, get the usermeta, then get those topics), and we
potentially want to be able to show what users favorited a plugin as well
(so, get the topicmeta, then show those users). While we're not actually
doing the latter at the moment, it's a potential case, so there it is.
Reviews are even more complex, since they integrate three things: users, a
plugin or theme, and a post in the support forums.
The problem you'll run into is one of making sure the data is synced across
the two. What happens when your process craps out after adding the
usermeta, but before adding the postmeta? This isn't a problem on a small
scale, but when you build to large scale, it will happen eventually.
In the long run, I think that we'll end up using a custom table for this,
in order to keep everything in a single location and to be able to query by
either case. Meta isn't a great fit for connecting two entirely disparate
sets of data together with a many-to-many relationship. There really is no
proper many-to-many metaphor in WordPress, as such. You can do it with
taxonomy, but that way lies madness. ;)
-Otto
-Otto
Post by chriscct7
Sounds like the best thing would be to store it in both places. Saves two
potentially expensive query's as your site scales up.
-Chris
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Post by chriscct7
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Gregory Lancaster
2013-11-11 18:58:16 UTC
Permalink
So I want to place this into a custom table instead, and if I am to do
that, to minimize the sql load I wont be using arrays. Rather the better
option would be to create a new row for each like, with one col for the
user_id that liked the post, another col for the post_id that was liked,
and a last col for for if the person who clicked like was logged in or not
to show how many anons or regular visitors liked the post.

That means everytime a post is loaded, a database call will be made to
query the table, grab all user_ids of for that post_id and run them through
a get_userinfo() or something right? That seems resource intensive.


On Mon, Nov 11, 2013 at 10:47 AM, Gregory Lancaster <
Post by Gregory Lancaster
Awesome answer, I was steering away from storing in a custom table because
people tell me OFTEN that I should always try to make use of the built in
wordpress meta fields available. But this makes sense.
Post by Otto
We implement plugin favorites on WordPress.org in a similar manner.
The plugin directory is a bbPress installation, so plugin entries are
"topics". When a user favorites a plugin, the ID of that topic is saved to
their usermeta, and the ID of that user is saved to the topicmeta.
The question is one of querying. We want to be able to show a user's
favorite plugins (so, get the usermeta, then get those topics), and we
potentially want to be able to show what users favorited a plugin as well
(so, get the topicmeta, then show those users). While we're not actually
doing the latter at the moment, it's a potential case, so there it is.
Reviews are even more complex, since they integrate three things: users, a
plugin or theme, and a post in the support forums.
The problem you'll run into is one of making sure the data is synced across
the two. What happens when your process craps out after adding the
usermeta, but before adding the postmeta? This isn't a problem on a small
scale, but when you build to large scale, it will happen eventually.
In the long run, I think that we'll end up using a custom table for this,
in order to keep everything in a single location and to be able to query by
either case. Meta isn't a great fit for connecting two entirely disparate
sets of data together with a many-to-many relationship. There really is no
proper many-to-many metaphor in WordPress, as such. You can do it with
taxonomy, but that way lies madness. ;)
-Otto
-Otto
Post by chriscct7
Sounds like the best thing would be to store it in both places. Saves
two
Post by chriscct7
potentially expensive query's as your site scales up.
-Chris
--
http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42772.html
Post by chriscct7
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Otto
2013-11-11 19:08:56 UTC
Permalink
On Mon, Nov 11, 2013 at 12:58 PM, Gregory Lancaster <
Post by Gregory Lancaster
So I want to place this into a custom table instead, and if I am to do
that, to minimize the sql load I wont be using arrays. Rather the better
option would be to create a new row for each like, with one col for the
user_id that liked the post, another col for the post_id that was liked,
and a last col for for if the person who clicked like was logged in or not
to show how many anons or regular visitors liked the post.
That means everytime a post is loaded, a database call will be made to
query the table, grab all user_ids of for that post_id and run them through
a get_userinfo() or something right? That seems resource intensive.
No more so than using meta, it's just that meta is more hidden from you.

Take the meta case:
- Query posts
- display post
- see that it has meta (pre-loaded for you by a normal WP_Query)
- Call get users to get the users and display them, or whatever

That query posts gets not only the posts, but all meta associated with
those posts. That's two queries, at least. Getting the users is your third
query.

Same case with a custom table:
- Get the posts (we don't care about meta here)
- get the custom table data
- get the users

Again, three queries that directly concern us.

The problem isn't really with the number of SQL queries, it's in making
those queries inexpensive.
- In both cases you get posts. Same deal.
- Getting meta for posts is actually kind of cheap, because it simply gets
all the meta data for all the loaded posts, so it's querying on the
post_id, which is indexed.
- Getting from your custom table is basically identical to that, because
you can put an index the post_id column. However, much less data to sort
through in this case, because it doesn't have all the other meta info
- Then in either case, you get the users. Same deal again.

Meta has a slight advantage in that it uses the WP_Cache system by default.
Lets say you run a WP_Query that gets a whole bunch of posts. The meta for
those is loaded and cached. Later, you run a query that also gets some of
those same posts. Because the meta is already cached, it doesn't go fetch
that data again. Time saved right there.

However, a custom table storing only ID numbers relating to other ID
numbers will be very small by comparison to meta, which has large text
fields in it. MySQL can optimize much better with small tables that connect
numbers to other numbers. Queries on that will be super quick. And if you
really want, you can implement caching using WP_Cache yourself, with
wp_cache_set and wp_cache_get. If it's needed, which it probably won't be
at first.

-Otto
BenderisGreat
2013-11-11 23:33:19 UTC
Permalink
Would this be the fastest way to check the database?

function alreadyLikedCheck() {
global $wpdb, $post, $current_user;
get_currentuserinfo();

$user_id = $current_user->ID;
$post_id = $post->ID;

$checkLikeTable = $wpdb->get_row( $wpdb->prepare('SELECT * FROM ' .
$wpdb->prefix . 'ams_post_likes' .' WHERE user_id = %d AND post_id = %d',
$user_id, $post_id ));
if (isset($checkLikeTable)) {
echo "You Like This Post";
} else
{ echo "<button type='button' id='post_like' data-id='".get_the_ID()."'
data-nonce='".wp_create_nonce('like_button')."'
data-user='".get_current_user_id()."' class='btn btn-success'>Like This
Post</button>"; }


}



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Like-Posts-Store-Data-in-DB-User-Meta-or-Post-Meta-tp42769p42796.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
Xavier Faraudo i Gener
2013-11-12 05:13:15 UTC
Permalink
Post by BenderisGreat
What would be the best option for storing which posts a user likes? They
click a like button, and it can be stored in the post_meta, or the
user_meta, or a sep db table. It seems to be that storing in the post_meta
would make the most sense, but I wanted to ask before moving ahead.
I'd seriously consider using neither of those, but an option. (Pun not
intended. I mean "I'd seriously consider using the wp_options table and
API".) At least for starters, until it's clear which kind of queries are
you going to run (and have a solid API).

Dilemma here would be if the keys for the option should be post ID or
user ID... But you can always hook at an early stage and add to cache
the "inverted"/"mirrored" data. F.i., if you have it stored in the form
user_id => array of post ids (with an option name like
"posts_liked_by_user_id"), you can add the array of post_id => array of
liking user_ids to cache. This way, you ensure data integrity much
better than by storing it in two places, and with no added queries. (And
you can copy the very option to cache, too, so you can access the data
consistently with wp_cache_get, instead of having to remember which one
was by get_option and which one by wp_cache_get.)

So, for instance (I'm not quite sure I've explained myself well), your
function could be something like:

function already_liked_check() {
global $post, $current_user;
if ( ! $post = get_post( $post ) )
return false; // not a valid post

$post_ids_liked_by_user = (array) wp_cache_get( $current_user->ID,
'posts_liked_by_user_id' );

/* or also
* $all_posts_liked_by_user_id = get_option( 'posts_liked_by_user_id' );
* $post_ids_liked_by_user = isset( $all_posts_liked_by_user_id[
$current_user->ID ] ) ? $all_posts_liked_by_user_id[ $current_user->ID ]
: array();
*/

if ( in_array( $post->ID, $post_ids_liked_by_user ) ) {
// User likes the post
} else {
// User does not like the post
}
}

Also, juggling with arrays alone you can also pull more-or-less easily
things like:

·Other posts liked by this user
·Other users who liked this post
·Users who liked this post also liked…
·Users who like similar things to user (checking how many matching like
posts both have)
·Most liked posts
·Most like-able users

… which makes for a nice basic set of features for a like-post addon.
--
Xavier Faraudo i Gener (the WordPress Web Warlock)
Loading...