当前位置: 首页 > 知识库问答 >
问题:

作业跟踪的批处理通知

权玉泽
2023-03-14

目前,我们使用三个嵌套的Foreach循环来获取运行批处理的信息。然而,我相当确定我们可以通过一个带有连接和子查询的MySQL语句来获取信息。

我们有大约30个类别,2000个用户。我们的目标是大约100个类别,拥有10万用户,尽管很明显Foreach循环并不理想(即使现在运行它们也需要大约一分钟)。

情况:用户希望得到通知,如果有工作可用于他们可以在某一领域做的贸易

目标:将批处理(每日、每周等)通知放入发件箱

技术:PHP、MySQL

到目前为止我所拥有的:

数据库:

 "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]

代码

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

所需的结果是user_id为键的job_ids数组[user_id]=

例如

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

编辑:

我可以为一个用户选择所有作业,这样效率会更高。但它仍然需要foreach用户。

   $category_id = get_category_from_notification_options($userid);
   $user_distance = get_user_work_distance($userid);
    "SELECT DISTINCT work.ID as 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 ) ) ) ) 
        AS distance 
        FROM work,user
        WHERE work.categoryID == $category_id
        HAVING distance < $user_distance
        ORDER BY distance";

共有2个答案

危璞
2023-03-14

在我看来,你拾取的距离似乎是从用户表中提取的(distance_from_center字段?)

SELECT DISTINCT ser.user_id, work.ID as 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 ) ) ) ) AS distance 
FROM notification_options
INNER JOIN jobs ON notification_options.category = jobs.category
INNER JOIN user ON notification_options.user_id = user.user_id
HAVING distance < user.distance_from_center
ORDER BY distance

编辑-如果您只想按距离顺序为每个用户创建一个作业列表(如果需要,您可以将其分解为一个数组以在php中进行处理-尽管使用上述查询来构建数组可能更容易),那么您可以使用以下方法:-

SELECT user_id, GROUP_CONCAT(workID ORDER BY distance)
FROM (
SELECT DISTINCT ser.user_id, work.ID as 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 ) ) ) ) AS distance 
FROM notification_options
INNER JOIN jobs ON notification_options.category = jobs.category
INNER JOIN user ON notification_options.user_id = user.user_id
HAVING distance < user.distance_from_center) Sub1
太叔京
2023-03-14

我认为你应该反过来做,使它更有效率。下面我将向您展示我用来创建查询的过程。因此,只有最后的查询是您所需要的。但我会解释这些步骤,这样也许对你将来有所帮助。

首先,我会选择所有的工作。如果您的目标是10万用户,那么很可能会有比用户少得多的工作。

select JOB.id, JOB.category
FROM table.work JOB

现在我们有了所有的工作,让我们看看哪些用户想要被通知。

select JOB.id, JOB.category, NOTIFY.user_id
FROM table.work JOB
LEFT JOIN table.notification_options NOTIFY
ON JOB.category=NOTIFY.category
WHERE NOTIFY.user_id IS NOT NULL

这将为每个作业创建一个列表,其中包含希望得到通知的所有用户ID。我添加了WHERE子句以从列表中删除所有没有人想看到的作业。现在我们可以JOINusers表来获取用户详细信息。

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) AS `distance`
FROM 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
WHERE NOTIFY.user_id IS NOT NULL
HAVING `distance`<=USR.distance_from_center
ORDER BY USR.user_id ASC, distance ASC

我在查询中包括了距离。请注意,我使用HAVING检查距离是否小于用户提供的距离。如果将其添加到WHERE子句中,则会出现一个错误,说明distance是未知列。我还添加了orderby类,首先根据用户ID排序,然后根据距离排序。这将使您更容易在PHP中创建所需的数组。

现在有很多方法可以实现每日/每周间隔。其中之一是为每个间隔创建单独的脚本,并且只选择设置它的用户。例如,您可以创建脚本“每日”。您每天运行的php,具有以下查询

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) AS `distance`
FROM 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
WHERE NOTIFY.user_id IS NOT NULL
AND USR.contact_frequency = 'daily'
HAVING `distance`<=USR.distance_from_center
ORDER BY USR.user_id ASC, distance ASC

现在我们有了查询,让我们为它创建PHP代码。我们可以循环所有行并创建数组。显然,您也可以直接处理结果,而不是创建数组。因为如果您先创建一个数组,您确实需要在之后再次循环该数组。

<?php
$arNotify = array();
foreach ($queryresult as $row) {
  $userid = $row->user_id;
  $jobid = $row->id;

  //check if there is an entry for the user in the database, else create it
  if (!array_key_exists($userid, $arNotify))
    $arNotify[$userid] = array();

  //and then push the job
  $arNotify[$userid][] = $jobid;

  //the array is being created, but I still like to process the job directly
  //notify_user($userid, $jobid);

}

var_dump($arNotify);
?>

这就是你想要的数组,作业按最接近的顺序排序。

 类似资料:
  • 我有以下工作要处理在一定的时间间隔或特别的基础上。 作业中的步骤如下: 我也想要用户界面,在那里我可以触发一个特别的基础上的工作,而且我应该能够提供参数从用户界面。 我想用Spring batch来完成这个任务,但它更多的是用于读->处理->写之类的工作。这里,在第一步中,我正在生成由第二步读取的数据。我不确定我是否还可以使用Spring batch来实现这个,或者有更好的方法来实现这个。

  • 我想使用电子商务跟踪我的网站,但我的网站不是一个传统的电子商务类型的网站。我们是一家船运公司,所以我们的订单是以运费为基础的。 网站的工作方式是客户在前端提交一个盒子来处理,然后在后端我们计算运输成本,然后批量运行我们所有的客户不同的货物。 有没有一种方法可以让我使用电子商务跟踪代码,并让它在我批处理所有货物时在后端通过每次发货循环? 谢谢你!

  • 问题内容: 我有一个执行一些模拟并以字符串格式返回数组的函数。 我想运行模拟(函数)以更改输入参数值(超过10000个可能的输入值),并将结果写入单个文件。 我正在使用多重处理,特别是pool.map函数来并行运行模拟。 由于运行仿真功能超过10000次的整个过程需要很长时间,因此我真的很想跟踪整个操作的过程。 我认为下面我当前代码中的问题是,pool.map运行该函数10000次,在这些操作过程

  • 我们正试图建立关于如何在大型IT服务中使用Spring Batch的标准,并具有不同的商业利益。 我们可能会有几个属于不同业务领域的批次。我们已经知道其中一些必须从所有批次通用的表中获取一些参数(即Java和COBOL;例如日期参数)。 我们将实现的Spring批处理作业的数量很难评估。没有重写现有COBOL批次的目标,只要有可能,就鼓励连续流程处理。 一些关于概念证明的问题不时出现,但目前几乎没

  • 我正在使用Spring batch进行批处理,在进行批处理之前,我想验证所有作业参数,如productName、productID、开始日期、结束日期、productType,如果这些作业参数为null或包含错误值,我必须使验证步骤失败,并使作业失败。 我已经编写了验证步骤和Tasklet,在我的Tasklet中,我计划处理作业参数验证(对所有作业参数执行空检查)。因为我是第一次做Spring批处