目前我们正在使用三个嵌套的 foreach 循环来获取运行批处理的信息。但是,我相当确定我们可以使用带有连接和子查询的单个 MySQL 语句来获取信息。
我们有大约 30 个类别和 2000 名用户。我们的目标是大约 100 个类别和 100000 个用户,但显然 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为key的job_id数组组成的数组 [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";
最佳答案
我认为您应该以相反的方式进行,以提高效率。下面我将向您展示我用来创建查询的过程。因此,只有最终查询才是您所需要的。但我解释了这些步骤,也许它会在未来对你有所帮助。
首先,我会选择所有作业。如果您的目标是 100.000 个用户,那么工作岗位很可能比用户少得多。
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 子句以从列表中删除没人想看到的所有作业。
现在我们可以JOIN users 表来获取用户详细信息。
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 是未知列。
我还添加了 ORDER BY 类,首先根据用户 ID 对其进行排序,然后再根据距离进行排序。这将使您更容易在 PHP 中创建所需的数组。
现在有很多方法可以实现每日/每周间隔。其中之一是为每个间隔创建单独的脚本,并且只选择设置它的用户。 例如,您可以创建一个每天运行的脚本“daily.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);
?>
你去吧,你想要的数组,作业按最接近的顺序排序。
关于php - 作业跟踪的批处理通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15378266/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:
是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述
我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby-vips的github页面上的链接,我们将不胜感激!如果有ruby-
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。
我想在Windows7上安装带有ruby1.9.3的rspec-railsgem。我收到一些错误消息,提示无法安装某些json库。所以,我使用下面的说明来解决它。来源=The'json'nativegemrequiresinstalledbuildtools从[rubyinstaller.org][3]下载[Ruby1.9.3][2]从[rubyinstaller.org][3]下载DevKit文件对于Ruby1.9.3,使用[DevKit-tdm-32-4.5.2-20110712-1620-sfx.exe][4]将DevKit解压到路径C:\Ruby193\DevKit运行cd
我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)
当profile为nil时,总是让我感到悲伤...我该怎么办? 最佳答案 在View中使用变量之前,始终检查变量是否为nil。我确信这个问题有更优雅的解决方案,但这应该能让您入门。 关于ruby-on-rails-Rails处理.Erb与Nils,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/2709605/