php - Batch processing notifications of job tracking -


at moment we're using 3 nested foreach loops information run batch. i'm sure information single mysql statement joins , sub-queries.

we have 30 categories 2000 users. our aim 100 categories 100000 users though foreach loops not ideal (even take minute run).

circumstance: users want notified if there work available trade can in area

goal: batch process (daily, weekly, etc) notifications put in outbox

technology: php, mysql

what have far:

database:

 "table.notification_options" : [id][user_id][category]  "table.user" : [id][user_id][method_of_contact][contact_frequency][center_of_work_area_long][center_of_work_area_lat][distance_from_center]  "table.work" : [id][post_date][longitude][latitude][category] 

code:

foreach user{     foreach category tracked{         foreach job in category posted <> $current_date-$batch_frequency{             if job inside workspace{                 notify_user(job);             }         }    } } 

the desired result array of arrays of job_ids user_id key [user_id]=>{jobs}

e.g.

    {         [user1]{                  job1,                  job4,                  job28                },         [user34]{                  job3,                  job4,                  job34,                  job78                 }      { 

edit:

i've got bit more efficient can select jobs 1 user. still requires foreach user.

   $category_id = get_category_from_notification_options($userid);    $user_distance = get_user_work_distance($userid);     "select distinct work.id workid, ( 6371 * acos( cos( radians(-46.409939) ) * cos( radians( jobs.lat ) ) * cos( radians( jobs.lng ) - radians(168.366180) ) + sin( radians(-46.409939) ) * sin( radians( jobs.lat ) ) ) )          distance          work,user         work.categoryid == $category_id         having distance < $user_distance         order distance"; 

i think should other way around make more efficient. below show process used create query. final query need. explain steps perhaps in future.

first select jobs. there lot less jobs users if goal 100.000 users.

select job.id, job.category table.work job 

now have jobs, lets see users want notified it.

select job.id, job.category, notify.user_id table.work job left join table.notification_options notify on job.category=notify.category notify.user_id not null 

this creates list each job, userid's want notified it. added where clause remove jobs list nobody wants see. can join users table user details aswell.

select job.id      , job.post_date      , job.longitude      , job.latitude      , usr.user_id      , usr.method_of_contact      , usr.contact_frequency      , usr.center_of_work_area_long      , usr.center_of_work_area_lat      , usr.distance_from_center      , ((acos(sin(usr.center_of_work_area_lat * pi() / 180) * sin(job.latitude * pi() / 180) + cos(usr.center_of_work_area_lat * pi() / 180) * cos(job.latitude * pi() / 180) * cos((usr.center_of_work_area_long – job.longitude) * pi() / 180)) * 180 / pi()) * 60 * 1.1515) `distance` table.work job left join table.notification_options notify on job.category=notify.category left join table.user usr on notify.user_id=usr.user_id notify.user_id not null having `distance`<=usr.distance_from_center order usr.user_id asc, distance asc 

i included distance in query. notice use having check if distance smaller user supplied. if add where clause error saying distance unknown column. added order by class first sort on user id , on distance. make easier create array want in php.

now there lot of ways implement daily/weekly intervals. 1 of them create seperate scripts each interval , select users set it. example, create script 'daily.php' run each day , have following query

select job.id      , job.post_date      , job.longitude      , job.latitude      , usr.user_id      , usr.method_of_contact      , usr.contact_frequency      , usr.center_of_work_area_long      , usr.center_of_work_area_lat      , usr.distance_from_center      , ((acos(sin(usr.center_of_work_area_lat * pi() / 180) * sin(job.latitude * pi() / 180) + cos(usr.center_of_work_area_lat * pi() / 180) * cos(job.latitude * pi() / 180) * cos((usr.center_of_work_area_long – job.longitude) * pi() / 180)) * 180 / pi()) * 60 * 1.1515) `distance` table.work job left join table.notification_options notify on job.category=notify.category left join table.user usr on notify.user_id=usr.user_id notify.user_id not null , usr.contact_frequency = 'daily' having `distance`<=usr.distance_from_center order usr.user_id asc, distance asc 

now have query, lets create php code it. can loop trough rows , create array. instead of creating array directly process result. because if create array first, need loop trough array again afterwards.

<?php $arnotify = array(); foreach ($queryresult $row) {   $userid = $row->user_id;   $jobid = $row->id;    //check if there entry user in database, else create   if (!array_key_exists($userid, $arnotify))     $arnotify[$userid] = array();    //and push job   $arnotify[$userid][] = $jobid;    //the array being created, still process job directly   //notify_user($userid, $jobid);  }  var_dump($arnotify); ?> 

there go, array want jobs sorted on closest first.


Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

Cross-Compiling Linux Kernel for Raspberry Pi - ${CCPREFIX}gcc -v does not work -

java.lang.NoClassDefFoundError When Creating New Android Project -