Easiest way to display a list of everyone whos added me as a buddy on my profile

Started by samborabora, July 07, 2014, 06:49:05 PM

Previous topic - Next topic

Arantor

QuoteOkay, let's say I am building extra functionality around it. Let's say I'm building a forum RPG system, or an awards system or a badges system or whatever.

Except I don't think you are, because if you were 1) you would have mentioned it and 2) you'd be able to do this yourself...

QuoteSo, here are two places that I can see where we would run into a run query set for checking if they are buddies or not. I'm not asking for anything amazing here, just if we can reverse the angle from "oh, I'm YOUR buddy" to "oh, you're MY buddy". The word buddy has lost all meaning anyways.

That's just it. Reverse angle is a massively different proposition. It's not in its own table, but in a format great for one way and terrible for the other. If you have a subset of users in the first place by way of online filtering, it's much cheaper. Doing it the way you want is not a cheap process because it has to use every single row of the members table (or hive it off to another table but *that*'s not a simple process either and has consequence either for performance or stability)

dougiefresh

Saw this thread this morning and decided this would be an interesting mod to create.....  Almost done.  :P

Arantor

So, FIND_IN_SET is your friend (and mildly force locking the entire members table)? Or are you querying (and force locking) the entire members table to get the reverse list?

What most people forget is that something which works fine on a small test environment won't scale to something a few orders of magnitude larger.

dougiefresh

I created a seperate table.  My only worry is that during install, when the mod script has to pull all member's buddy lists, that the script will run out of memory.  I've wrote seperate functions to manage the new table and added a page in the profiles to list the results....

Besides, FIND_IN_SET would have to process the entire member's list and I'd rather not have to process that mess every time someone wants to look at the list.....  Once is enough....

Arantor

So, there's the question, are you keeping them in sync with the master ones (so that all the other behaviour is maintained), and what do you have in place to fix out of sync cases?

Or are you reworking all the other places to use this new table (which has its own performance connotations)?

QuoteMy only worry is that during install, when the mod script has to pull all member's buddy lists, that the script will run out of memory.

I'd be more worried about hitting the time limit than I would memory.

QuoteBesides, FIND_IN_SET would have to process the entire member's list and I'd rather not have to process that mess every time someone wants to look at the list.....  Once is enough....

It's almost like I didn't point this fact out throughout this topic. I mean, am I new to SMF or something?

dougiefresh

Quote from: ‽ on July 11, 2014, 06:02:00 PM
So, there's the question, are you keeping them in sync with the master ones (so that all the other behaviour is maintained), and what do you have in place to fix out of sync cases?
Yeah, I'm keeping them in sync so that the other behavious is maintained....  Huh, I didn't think about how to resync them  ???  Back to the drawing board  :P

Quote from: ‽ on July 11, 2014, 06:02:00 PM
Or are you reworking all the other places to use this new table (which has its own performance connotations)?
Just displaying them there in the Profile page.  (So far)

Quote from: ‽ on July 11, 2014, 06:02:00 PM
QuoteMy only worry is that during install, when the mod script has to pull all member's buddy lists, that the script will run out of memory.

I'd be more worried about hitting the time limit than I would memory.
Hmmm....  What to do, what to do.....

Quote from: ‽ on July 11, 2014, 06:02:00 PM
QuoteBesides, FIND_IN_SET would have to process the entire member's list and I'd rather not have to process that mess every time someone wants to look at the list.....  Once is enough....

It's almost like I didn't point this fact out throughout this topic. I mean, am I new to SMF or something?
LOL!  Nah, I never meant to imply that!  I meant that locking the member list only once was enough to build the list.  After the new table is built, then it's easy-peasy to maintain....

Arantor

QuoteHmmm....  What to do, what to do.....
Well, consider it this way: you're doing a query to get the member id and their buddy list and you're iterating over that resultset with a while loop all the time mysql_fetch_assoc returns non-false.

From there you're going to be building an interim array of rows that will go into your new table. You can quite happily fill that array up and periodically push it to the table - you can quite happily have two queries going on, then empty the array to release memory back to the GC (well, maybe, that's another story)

QuoteI meant that locking the member list only once was enough to build the list.  After the new table is built, then it's easy-peasy to maintain....

True enough but on the other hand, you then end up with a table that needs to be kept in sync with other things - and presumably you will want to suitably index that table (fortunately the RDBMS will handle that for you)

It's a complex battle, and even displaying it on profile is not something I'd be huge on even with all the other issues, simply because the profile is already surprisingly expensive.

dougiefresh

Quote from: ‽ on July 11, 2014, 06:42:49 PM
QuoteHmmm....  What to do, what to do.....
Well, consider it this way: you're doing a query to get the member id and their buddy list and you're iterating over that resultset with a while loop all the time mysql_fetch_assoc returns non-false.

From there you're going to be building an interim array of rows that will go into your new table. You can quite happily fill that array up and periodically push it to the table - you can quite happily have two queries going on, then empty the array to release memory back to the GC (well, maybe, that's another story)
The way I've got my script set up, the problem is that even though the members are pulled in sequential order, the result table is built haphazardly according to whom each member is buddies with.  So if member 1 is buddies with 5 people and member 900,000 is buddies with member 1, then it's gonna be a while before member 900,000 is processed, and if I have pushed the array to the table, then I can't very well update member 900,000 as  buddies with member 1's because member 1's element in the array is gone....  (I'm not sure if I'm relaying the problem correctly...  ether that or I don't understand what you said  :P )

Lemme think about how to approach this issue....  It'll probably have something to do with the resync function, as it needs to written anyways and I could solve that problem there.....

Arantor

Oh, I see what you're doing. That's not what I was getting at, nor how I would approach it. Building and maintaining such a flattened relational map is not ideal but it really depends on whether you have any plans for the data.

The way I'd approach this is to build a relational map in the conventional sense - a table showing id_member, follows: e.g. if id_member 1 has a buddy list of 2,3,4, you'd have the following table:

1, 2
1, 3
1, 4

with a combined primary key of id_member, follows and a conventional index of follows.

Having the index on follows means you can query on that without any headache. If we were, for example, to say that the above was the only list of relationships in the system, we could obtain the number of followers of id_member 2 by querying where follows = 2.

Now, you might say that purposefully flattening the list makes it more performant but in practice it usually doesn't, and this gives you other options in terms of what you do with the data; for a very simple list of names you can obtain the names without even doing another query by doing a join.

For example, a list of the names and id_members of all the people that follow user id 3 and as a bonus, sort by user name:

SELECT mem.real_name, mem.id_member
FROM {db_prefix}followers AS f
INNER JOIN {db_prefix}members AS m ON (f.id_member = mem.id_member)
WHERE f.follows = 3
ORDER BY mem.real_name

This means avoiding the loadMemberData monster (bearing in mind that lMD will invoke 1 query in minimal mode, 2+ queries in any other mode, often 3).

Plus you can do any other processing you like here, with little extra effort. Want to exclude banned members? Easy: WHERE f.follows = whatever AND mem.is_activated < 10

dougiefresh

Dang it.... I hate it when someone gives me a better idea how to do something AFTER I've written my code  :P O:)  Back to the proverbial drawing board.... 8)

EDIT: Man, this simplified my code greatly!  Thanks, ‽ !!!

Arantor


dougiefresh

Okay, here's an update: I'm using a script to add table during the install and it redirects to the resync function.  The resync function has been built so that it loads a template every 10 seconds to restart the process at the point it left off at, unless it has completed the task....  then it reports done.  Almost done with resync function....

Arantor


dougiefresh

Yup....  Sure can!  I just hadn't gotten that far yet!  Thanks again for the advice!

Followers List v1.0 mod released....  Waiting for approval.  8)

samborabora

Quote from: dougiefresh on July 13, 2014, 09:30:47 PM
Yup....  Sure can!  I just hadn't gotten that far yet!  Thanks again for the advice!

Followers List v1.0 mod released....  Waiting for approval.  8)

Wow, is this finished? Have you got it available anywhere like github so I can give it a test spin?

dougiefresh

Quote from: samborabora on July 14, 2014, 02:42:35 PM
Wow, is this finished? Have you got it available anywhere like github so I can give it a test spin?
Yup yup....   ;D Impatience we are...   ::) Check your PMs....

samborabora

Quote from: dougiefresh on July 14, 2014, 06:51:15 PM
Quote from: samborabora on July 14, 2014, 02:42:35 PM
Wow, is this finished? Have you got it available anywhere like github so I can give it a test spin?
Yup yup....   ;D Impatience we are...   ::) Check your PMs....

How long does it take for a mod to be approved? The version you sent works really well so far, need to do some thorough testing to be certain at the minute. I'm using a link to add and remove buddies on the users profile, does this somehow work differently with the buddy's list add/remove mothod, because if I add users via the buddy list, they show up on the other users followers perfectly, however if I use a link to add or remove a buddy, it does not reflect on the followers list. Here's the code I'm using for my add/remove link on profile.template.php:

// Can they add this member as a buddy?
//ALREADY BUDDY
if (!empty($context['can_have_buddy']) && !$context['user']['is_owner'] && !$context['member']['is_buddy'] )
echo '
<span class="profefol"><a href="', $scripturl, '?action=buddy;u=', $context['id_member'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['buddy_add'], ' ', $context['member']['name'], '</a></span><br />';
//NOT YET A BUDDY
if (!empty($context['can_have_buddy']) && !$context['user']['is_owner'] && $context['member']['is_buddy'] )
echo '
<span class="profeunfol"><a href="', $scripturl, '?action=buddy;u=', $context['id_member'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['buddy_remove'], '</a></span><br />';


Would I need something else in there to make the followers table populate/depopulate upon clicking?

dougiefresh

Quote from: samborabora on July 15, 2014, 04:55:48 PM
How long does it take for a mod to be approved?
As long as it takes.....

Quote from: samborabora on July 15, 2014, 04:55:48 PM
The version you sent works really well so far, need to do some thorough testing to be certain at the minute. I'm using a link to add and remove buddies on the users profile, does this somehow work differently with the buddy's list add/remove mothod, because if I add users via the buddy list, they show up on the other users followers perfectly, however if I use a link to add or remove a buddy, it does not reflect on the followers list.  Would I need something else in there to make the followers table populate/depopulate upon clicking?
I must have missed that method of adding/removing buddies....  I'll add it and submit it....

samborabora

Quote from: dougiefresh on July 16, 2014, 07:02:12 PM
Quote from: samborabora on July 15, 2014, 04:55:48 PM
How long does it take for a mod to be approved?
As long as it takes.....

Quote from: samborabora on July 15, 2014, 04:55:48 PM
The version you sent works really well so far, need to do some thorough testing to be certain at the minute. I'm using a link to add and remove buddies on the users profile, does this somehow work differently with the buddy's list add/remove mothod, because if I add users via the buddy list, they show up on the other users followers perfectly, however if I use a link to add or remove a buddy, it does not reflect on the followers list.  Would I need something else in there to make the followers table populate/depopulate upon clicking?
I must have missed that method of adding/removing buddies....  I'll add it and submit it....

I gave this version a go, and now the add buddy link just goes to a white blank screen! I tested after uninstalling it, and it works if the mod is not installed, so this versions definitely causing something to break, I'm afraid!

dougiefresh

Quote from: samborabora on July 17, 2014, 12:39:15 AM
I gave this version a go, and now the add buddy link just goes to a white blank screen! I tested after uninstalling it, and it works if the mod is not installed, so this versions definitely causing something to break, I'm afraid!
The only add buddy link that I'm aware of is in the Profiles page of another user.  My tests work fine for that.  So I assume that you're using custom code....  correct?

Advertisement: