472,125 Members | 1,496 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,125 software developers and data experts.

User Information Privacy Levels DB design

bilibytes
128 100+
Hi everyone,

I'm facing a database design problem.
I want to make a sort of networking solution for the clients of my site in which they would be able to share or keep private some of their contact information.

so if i have a table like this:

Expand|Select|Wrap|Line Numbers
  1. CREATE TABLE `users_retailers_account_info` (
  2.   `id` bigint(15) unsigned NOT NULL auto_increment,
  3.   `email` varchar(255) NOT NULL default 'N/A',
  4.   `password` varchar(255) NOT NULL default 'N/A',
  5.   `name_first_owner` varchar(255) NOT NULL default 'N/A',
  6.   `name_second_owner` varchar(255) NOT NULL default 'N/A',
  7.   `company_name` varchar(255) NOT NULL default 'N/A',
  8.   `country_id` mediumint(8) NOT NULL default 'N/A',
  9.   `city_id` varchar(255) NOT NULL default 'N/A',
  10.   `street_address` varchar(255) NOT NULL default 'N/A',
  11.   `lang_iso` varchar(5) NOT NULL default 'en',    
  12.   PRIMARY KEY  (`id`)
  13. )
i would like to be able to set some of the columns as having different privacy levels.

The problem is that as far as i know, there is no possibility to put metadata to a column like:
Expand|Select|Wrap|Line Numbers
  1. [public] street_address | 4th avenue, Manhatan
  2. [protected] email | johnleehooker@hotmail.com
note that i dont want it to be permanent, i want to let the user decide which privacy levels give to any personal acount information (except for password...).

My first approach to solve this, was to make a big table, with the columns names, field values and privacy levels like this :
Expand|Select|Wrap|Line Numbers
  1.  CREATE TABLE `privacy_levels` (
  2.   `id` bigint(15) NOT NULL auto_increment,
  3.   `user_id` bigint(15) NOT NULL auto_increment,
  4.   `column_name` varchar(255) NOT NULL default 'N/A',
  5.   `field_value` varchar(255) NOT NULL default 'N/A',
  6.   `privacy_level` varchar(20) NOT NULL default 'private',
  7.   PRIMARY KEY  (`id`)
  8. )
whenever a user sets a different privacy setting than the default, the name of the column and the field value would be stored in this privacy levels table with the desired privacy.
However this approach has a lot lot lot of overhead. and would make the table very large and slow to query.

Then i thought of another approach which was to give the users_retailers_account_info column a privacy_level pair column like this:
Expand|Select|Wrap|Line Numbers
  1. CREATE TABLE `users_retailers_account_info` (
  2.   `id` bigint(15) unsigned NOT NULL auto_increment,
  3.   `email` varchar(255) NOT NULL default 'N/A',
  4.   `privacy_email` varchar(20) NOT NULL default 'private',
  5.   `password` varchar(255) NOT NULL default 'N/A',
  6.   `name_first_owner` varchar(255) NOT NULL default 'N/A',
  7.   `privacy_nfo` varchar(20) NOT NULL default 'private',
  8.   `name_second_owner` varchar(255) NOT NULL default 'N/A',
  9.   `privacy_nso` varchar(20) NOT NULL default 'private',
  10.   `company_name` varchar(255) NOT NULL default 'N/A',
  11.   `privacy_company` varchar(20) NOT NULL default 'private',
  12.   `country_id` mediumint(8) NOT NULL default 'N/A',
  13.   `city_id` varchar(255) NOT NULL default 'N/A',
  14.   `street_address` varchar(255) NOT NULL default 'N/A',
  15.   `privacy_street_address` varchar(20) NOT NULL default 'private',
  16.   `lang_iso` varchar(5) NOT NULL default 'en',    
  17.   PRIMARY KEY  (`id`)
  18. )
so when a user requests to get info from a certain retailer, the application would query all the table fields and only show those whose privacy is set to public. but I don't know if this is the right approach.

If you have any suggestions, please let me know.

Thank you for reading this far,

best regards


bilibytes
Mar 5 '09 #1
8 2069
I like the idea of metadata. You could pre-pend the metadata with the public/private value, use whatever delimeter, and then split the value with your script, limiting it to only one split.

so, for example, email would look like
private;myemail@email.com

then, when you queried the table, you would run something like this (I'm using php as an example, not sure what script you're using)
Expand|Select|Wrap|Line Numbers
  1. $email = mysql_query("SELECT email FROM users_retailers_account_info WHERE id = "$userid" ");
  2. $email = mysql_fetch_array(explode(";", $email, 2));
  3. if($email[0] == "private"){
  4. //do not display email
  5. }else{
  6. //display email
  7. }
  8.  
You could conceivably cut down even more on overhead by reducing private/public to 0/1.

You would have to make sure though that every time you manipulated the data, you would need to split the string. You could probably just create a function for that...

Anyway, hope this helps...
Mar 5 '09 #2
bilibytes
128 100+
@chemlight
Thank you very much for your help!
You think it's the most efficient way? even if I have to subtract the privacy value from each fetched column?

thank you again

by the way, you exploded the string in the wrong order. you should first use mysq_fetch_array($result) and to the result of that function you should explode the value.
(I know you know how to do it and it was a typing mistake, but i point it out so that new coders don't get misled)

regards
Mar 6 '09 #3
Not sure if its the best. I don't know how to test script speeds, but thats how I would think of doing it...(note the "newbie" under Chemlight :-) )
Mar 6 '09 #4
bilibytes
128 100+
@chemlight
lol that newbee just means you are new to the site... :) not necessarily newbee to programming.
I just posted a thread on php script testing under php section. if you wait that someone answers we'll be able to test our scripts!

i'll dig deeper in the content privacy table design. thanks for your help anyway

regards
Mar 6 '09 #5
@bilibytes
Lol. I just posted a thread on that too...

:-)
Mar 6 '09 #6
Here's the code that I speed tested:

Expand|Select|Wrap|Line Numbers
  1. function microtime_float()
  2.         {
  3.             list($usec, $sec) = explode(" ", microtime());
  4.             return ((float)$usec + (float)$sec);
  5.         }
  6.  
  7.         $time_start = microtime_float();
  8.  
  9.         $i = 0;
  10.         while($i < 1000){
  11.             $info = mysql_query("SELECT email, email_privacy FROM testtable2 WHERE id = '1'");
  12.             while($row = mysql_fetch_array($info)){
  13.                 $email = $row['email'];
  14.                 $privacy = $row['email_privacy'];
  15.             }
  16.             $i++;
  17.         }
  18.  
  19.         $time_end = microtime_float();
  20.         $time = $time_end - $time_start;
  21.  
  22.         echo "<br />Did nothing in $time seconds\n";
  23.  
  24.         $time_start = microtime_float();
  25.  
  26.         $i = 0;
  27.         while($i < 1000){
  28.             $info = mysql_query("SELECT email FROM testtable1 WHERE id = '1'");
  29.             while($row = mysql_fetch_array($info)){
  30.                 $emailsplit = explode(";", $row['email'], 2);
  31.                 $email =  $emailsplit[0];
  32.                 $privacy =  $emailsplit[1];
  33.             }
  34.             $i++;
  35.         }
  36.  
  37.         $time_end = microtime_float();
  38.         $time = $time_end - $time_start;
  39.  
  40.         echo "<br />Did nothing in $time seconds\n";
  41.  
The two differences in the scripts are that the first must query a result from two fields, and doesn't need to explode the variables, whereas the second only needs to query from one field, but has to use explode to get the variables.

Here were the results from Multiple tests:
Did nothing in 0.121823072433 seconds
Did nothing in 0.110490083694 seconds

Did nothing in 0.120975017548 seconds
Did nothing in 0.112523078918 seconds

Did nothing in 0.119637012482 seconds
Did nothing in 0.11141705513 seconds

There are 21,000 of the same entry in each table. The table formats/data are
testtable1
id | email
1 | 0;myemail@email.com

testtable2
id | email | email_privacy
1 | myemail@email.com | 0

The table sizes (again, with 21,000 entries) are:
testtable1 = 786.2KiB
testtable2 = 786.3KiB

I don't know what is considered worthwhile with speed and overhead, and I'm only testing the difference in overhead with very few fields(although very many records). But, the speed and overhead of using split seems to be better and more efficient.
Mar 6 '09 #7
bilibytes
128 100+
wow, i really appreciate what you did!! that is great!
thank you very very much!

tomorrow i'll fill my tables with some content and i'll do some tests re adapting your code. and i'll post the verdict here if it is different to yours.
Mar 6 '09 #8
I look forward to it!
Mar 6 '09 #9

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

1 post views Thread by farsad nasseri | last post: by
3 posts views Thread by Martin Lacoste | last post: by
4 posts views Thread by morc | last post: by
95 posts views Thread by hstagni | last post: by
5 posts views Thread by Phil | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.