一个优秀的数据团队由什么组成?

数据团队很难招募。工程师的供应量低,需求量大,如果没有耗时的电话/编码屏幕,甚至没有FAANG,就很难审查简历。’的资源,很难找到像您一样对产品充满热情的人。作为招聘经理,您可能有幸负担得起专业招聘人员的服务。但是,招聘人员通常会向您发送完全不合适的候选人。

我在纽约认识一位非常友好的招聘人员,前几天我喝咖啡来讨论这些行业问题。我们一致认为,如果我们定义什么构成了一个很好的数据团队以及这些角色实际上意味着什么,那将很有用。

我应该首先雇用谁?他们如何一起工作?

  • 数据分析师
    • 雇用数据团队的目标可能是业务洞察力,并在某种程度上使您的行动主要由数据(而非直觉)驱动。为此,您需要一个有能力的数据分析师。值得庆幸的是,数据分析师的人数很多。渴望挖掘洞察力并具有定量或半定量(例如Econ)背景的新毕业生不应该’太难找了。在高端,您可以找到具有SQL经验的人以及相对较新的BI工具(如Looker)。如果您有预算,则可以使用即插即用的流水线工具(例如细分)解决75%的工程任务。最标准的业务见解– “昨天/上个月发生了什么?”, “what’我的客户群中服务不足的人群?”没有昂贵的数据科学家就可以回答。
  • 数据工程师
    • 在某些时候,您的数据库和查询将变得太慢。您’ll还想抓取数据源或使用没有人为Segment中的连接器建立过的API。也许你’我想要一些定制的销售线索评分’一堆安全问题’您希望每天早晨刷新一些庞大的查询,并在Slack中通知您。没有编程背景,您的数据分析师会感到不胜其烦。这是您需要雇用数据工程师的时候。他们的专业知识真正在于使您的数据集达到可分析的地步。如果您的表每月收到5000万个事件,那么查询将在一夜之间开始花费数小时,并且表甚至可能被锁定。数据工程师可以缓解这种情况– they 将能够优化数据库的索引’用于快速查找的s表,创建每天早晨刷新的有用聚合的物化视图,将自定义API连接到您的数据仓库,并且通常超出即插即用工具所涵盖的范围。 
  • 数据科学家
    • 现在你’重新获得标准的业务见解,并从有趣的来源中大规模获取它们’几乎肯定会对AI的警笛声感到好奇。如果您可以预测哪个客户会流失/转换,该怎么办?如果您可以按行为将客户群聚在一起怎么办?称职的数据科学家有可能提供这种更深入的了解。他们将使用Python中的机器学习库来尝试自动对您的客户和系统中的操作进行分类。他们可以预测未来(以一定的准确性),并告诉您有关数据的故事。这将涉及使用数据工程师提供的大型数据集。一旦这些见解浮出水面,他们将获得训练有素的模型,可以将其保存到磁盘并进行刷新。但是,如果需要每天刷新一次,并将这些见解添加到数据分析师甚至销售员可以读取的表中,该怎么办?然后,您需要返回到数据工程师,并让他们设置一个后端系统来执行此操作。
  • 数据科学工程师,机器学习工程师
    • 有时,您的(可能是较老派的)数据工程师将100%专注于管道和数据库管理员,并且在实施数据科学家想出的基于Python的模型方面没有特别的经验。对于此问题,您需要一名数据科学工程师或机器学习工程师。他们的专长是部署,扩展和刷新数据科学家提出的模型。数据科学家应该完全专注于概率,调整模型参数和置信度分数;您的数据分析师应该专注于更高层次的叙述,而您的DS / ML工程师现在可以采用该模型,并确保该模型可以快速提供您的见解,并提供干净,新鲜,正确的数据。
  • 可视化工程师
    • 如果Looker没有,该怎么办’没有您想要的图表?如果您需要可视化网络怎么办?如果您的数据有16个维度并且您’是否已用完散点图中的所有颜色,大小和形状选项?然后,您需要可视化工程师的非常专门的角色来构建自定义可视化并想出更好的方法来揭示数据分析师难以解决的见解。
  • 商业智能工程师
    • 这是一个模棱两可的标题–他们可能是数据科学工程师或数据工程师。

的角色

标题 工作职责 工具/技术
数据分析师  基本业务见​​解 外观 / Tableau,SQL,Excel,Redash
数据科学家 更复杂的业务预测 Jupyter笔记本,Python,Scikit-Learn,Numpy,Scipy,Statsmodels
数据工程师 得到“Big Data”到可以分析以及连接自定义数据源的地步 SQL,Python,Scrapy,Spacy,Selenium,Kafka,Airflow,Luigi,Spark,AWS,Redshift
数据科学工程师或机器学习工程师 实施数据科学家’s models at scale SQL,Python,Scikit-Learn,Numpy,Scipy,AWS,TensorFlow
可视化工程师(稀有) 制作精美的图形以增强每个人’s work 外观 / Tableau,Javascript,D3.js,Highcharts,HTML

但是,为什么每个人都只专注于数据科学?

数据科学是一个流行词,有人用它来表示适合数据工程和分析交叉领域的任何人。公司犯下的最大错误之一就是雇用了太多的数据科学家而没有足够的数据工程师。最近,许多前数学家,化学家,统计学家和其他数量级的毕业生发现,数据科学家正在变得更容易招聘,他们可以轻松地重塑自己的形象或参加3个月的Bootcamp并担任初级职位。但是,他们的模型和洞察力可能会受到限制,因为他们没有’不知道如何扩展/部署它们;他们将花费大量时间来清理数据集,而不是专注于隐藏在其中的消息和预测。当然,作为一个现在主要专注于数据工程的人,我有偏见,但是我想说,每个数据科学家都应与至少一名数据工程师配对。我实际上从数据科学专业转到数据工程专业的原因确实是出于我自己工作的需要。

我希望本指南今天能成功解释’的数据团队。如果您有任何改进建议,请发表评论或给我发送电子邮件。

开源DIMA–方便的数据库监视工具

框架上的数据

在像 框架,我们将收到大量数据-每月超过6700万个事件。高效的分析对于保持市场领导者地位至关重要,我们使用大量工具:

  • GUI之类的 外观Redash and 续集
  • 内部分析和查询并行化微服务
  • 我们为垃圾邮件/入侵检测和销售线索发现而构建的定制AI Slackbots

这意味着我们的数据仓库经常受到大量查询的攻击,无论是在Cron计划中还是在员工探索我们的数据集方面都如此。

数量问题

管理如此大量的查询可能很困难。

  • PostgreSQL表可以锁定-例如,在其他人查询表时尝试交换/删除表将导致它们锁定。理想情况下,分析表仅应进行增量更新,但有时设计限制会阻止这种情况。
  • SQL GUI可能会随机超时,这对快速检查数据库以查看它们是否仍在运行很有用。
  • 使用 a combination of screen and psql to run queries in the background requires monitoring. Dima is great for that.
  • 数百万行表上没有LIMIT的意外SELECT可能会使SQL GUI崩溃。
  • 有时候,一个大查询不是您想要的。 伪装l没有取消按钮,而托管的GUI(如Redash和Looker)具有“取消”按钮,这些按钮对于长时间运行的查询通常无响应。

迪玛

为了帮助解决此问题,我构建了一个名为dima的小型命令行工具。它最初代表“数据库完整性监控”&分析”,但现在只是“ dima”。它非常简单,而且非常有用,因此我可以将其开源。

Dima is a Python script that basically lets you quickly summarize or inspect the pg_stat_activity internal table in Postgres via the psycopg2 library. If you want to kill a query it will call pg_terminate on the PID.

查看 //github.com/Frameio/homebrew-dima.

安装 using pip install dima-db or 酿造 tap Frameio/homebrew-dima && brew install dima

指令

dima —正在运行的查询摘要

dima show [PID] -检查特定的正在运行的查询

dima rm [-f] Some PID or Keyword —杀死查询/查询

我们如何在Frame.io中分配注册

为60万用户分配800M点击

在 框架 we use 分割 支持我们的应用使用情况分析。可以通过使用事件名称(例如“注册“ 要么 ”观看视频”。

此数据对于我们的A / B测试和分析至关重要。与细分市场与以下服务的出色集成相结合 明比特,我们可以使用公司信息来丰富个人资料,然后跟踪用户首次访问我们的任何服务。这些数据使我们能够确定哪些博客作者吸引了最高的LTV客户,哪些YouTube潜在受众群体产生了最少的粘性用户,等等。

我们利用各种不同的渠道来发展-滴灌电子邮件广告系列,Facebook,YouTube,Twitter,Google AdWords,它们都有各自独立的平台,其中一些并不同步到我们的数据仓库中。需要一个系统来均匀化此信息,以便我们可以在一个地方分析客户,渠道,活动和媒体。

归因实际上是从360度角度了解公司的市场契合度,以及其向正确的受众简要说明其服务的能力。

规划归因系统

从概念上讲,归因非常简单-只需在数据库中找到用户ID的第一个结果并提取UTM,对吗?但是,在获取显示用户来源的那一行数据之前,需要进行大量考虑:

  • 即使建立了很好的索引,每天仍要在数百万行中搜索数千个用户,并维护这些行后面的分区和索引可能对数据库造成很大的负担。
  • 用户首次访问该网站时,他们没有user_ids,而是由Segment分配的onymous_id。用户ID仅在用户创建帐户后才与该用户相关联,并且“ iy”呼叫同时使用anonymous_id和user_id。有时,我们会发现一年多以前用户的anonymous_id。拥有用户的全局ID(从系统分配)后,我们必须在分配ID之前回填所有匿名会话。
  • 在注册之前,我们必须对每组用户操作进行会话,并汇总有关其第一次/最后一次会话的属性。会话化是将离散的用户事件聚合到页面加载过程中的过程,间隔不超过20分钟。这使我们能够做一些事情,例如分析访问的整体意图并进行批量归因。重新会话涉及巨大的嵌套窗口函数和别名表,因为同一用户经常要合并几个历史的匿名ID。
  • 我们将希望维护一些快速查找表以使其有用。-用户会话计数,有用的会话,也许还有一些汇总,以了解我们在可视化工具(如可视化工具)中的工作方式 外观.
  • 另请注意,细分实际上具有本地 归因 您可以安装带有摘要的系统;但在安装之前无法回溯。,我们的数据可以追溯到2014年。

实施阶段

系统设计基于以下8个查询组/阶段:

  1. 在现有的会话化数据中查找最新的时间戳
    1. 从细分跟踪表中获取所有最新访问数据
    2. 将此数据与最近的每月分区合并,并使用一些代码来检查列是否仍然相同(可以添加新字段)。
  2. 会话化最近的分区(最近24小时可能有重叠,因此请确保覆盖了空白)
    1. 用任何新标识的匿名/用户对更新别名表。
    2. 返回所有历史会话并重新别名-即将匿名ID替换为任何新标识的user_id。
    3. 重新会话化所有历史会话,因为相邻的会话在历史上可能具有不同的匿名ID,但现在具有相同的user_id
  3. 添加额外的一列以指示用户是否注册了会话
    1. 将生成的会话表合并到单个all_sessions表中
    2. 为有用的会话创建查找表-这是第一个会话,并且仅针对每个用户的注册会话
  4. 创建一个有用的归因表,其中包含预先提取的UTM参数和会话计数
  5. 重新索引所有表,并检查分区顺序是否正确(尤其是在新的月份间隔内)。

表结构

表/图式:

  • 混叠
  • 会议
    • 归因
    • all_sessions
    • 有用的会话
  • session_stages
    • all_tracks_2018_01
    • all_tracks_2018_01_aliased
    • all_tracks_2018_01_re_merged
    • all_tracks_2018_01_signup
    • …etc
  • 分割
    • 应用程式_tracks_2018_01
    • 应用程式_tracks_2018_02
    • 应用程式_tracks_2018_03
    • …etc

最终的sessions.attribution表中的列(许多只是快速查找,易于聚合,并且该表已建立大量索引):

  • alias_id
  • session_count_before_signup
  • signup_timestamp
  • blog_url
  • first_page_ever_visited
  • 首次接触(即与任何frame.io属性的首次互动)
    • 时间戳记
    • 来源,广告系列,媒体,引荐来源
  • 最后一次接触(即注册前的最后一次互动)
    • 时间戳记
    • 来源,广告系列,媒体,引荐来源
  • 首次归属接触(如上所述,但带有付费推荐人)
    • 时间戳记
    • 来源,广告系列,媒体,引荐来源
  • 最后归属的联系方式(如上所述,但带有付费引荐来源)
    • 时间戳记
    • 来源,广告系列,媒体,引荐来源

部署和监控

该系统花了大约1.5个月的时间才能正常运行,并且需要大约800行代码(Python,SQL,Shell和YAML)。

像AWS,Google Cloud和Azure这样的云计算生态系统使部署这样的微服务变得非常简单。该代码是Dockerized(在 高山的)并部署在 ECS Fargate 簇。新的版本由处理 代码管道,它监视Github仓库的归属。基础数据库是 极光Postgres.

该系统每天早上大约需要运行4个小时,并且可能会遇到诸如底层表缓慢或不可用之类的困难。为了减轻这种情况,每个查询都有一个2小时的重试系统。

性能已登录 AWS Cloudwatch,已同步到 数据狗。如果重试后任何查询完全失败,则 寻呼机 ping已发送到我的手机。

结果

  • 出色的统计信息-71%的用户在第一次访问时就注册了!
  • 对Frame.io采取了8亿个操作(我们的细分跟踪表分区的行数-),我们现在有60万用户。
  • 我们不再需要深入研究特定的平台(例如Facebook Business,Google Analytics(分析)),而是将所有分析都集中在一个地方并可以在Looker中将其可视化!
  • 通过简单的SQL分组依据,我们可以轻松计算出每个广告系列或频道的平均LTV。
  • 我们可以评估来源的粘性-例如我们的YouTube广告能为我们带来长期或快速流失的客户吗?
  • 作为直觉检查,我们要求用户报告他们听说过Frame.io的位置(直接访问的比例为50%,YouTube的比例为14%,Facebook的比例为10%),这些数字与我们的“首次触摸”列完全匹配。

我们从这里去哪里?

  • 此归因系统只是实际分析背后的管道。当我们不得不做出更多的哲学决定时,这将变得更加困难。我们如何确定如何归因于“多点触控”用户?例如。如果用户在一篇博客文章上具有第一接触,而几个月后在另一文章上具有最后接触,那么谁能得到功劳呢?
  • 我们目前正在密切监视性能,该过程大约需要4个小时。但是,我们的流量每个月都在以惊人的速度增长-这种持续时间将持续多长时间?值得庆幸的是,该系统除了最后阶段外,还易于并行化。

 With thanks to Kyle Gesuelli and Ammon Brown for proof reading, edits and suggestions. I originally posted on the Frame.io blog at: //medium.com/frame-io-engineering/marketing-attribution-at-frame-io-8c2dbde14b37

避免使用顶级导入进行多次读取

最近我’一直在与需要导入大型JSON定义文件的各种应用程序一起使用,这些文件定义了复杂的应用程序设置。通常,代码库中的多个辅助模块都需要这些文件。所有软件工程原理都指向仅一次导入此类文件,而不管其使用了多少个辅助模块。

我的本能方法是在文件中读取一个主处理程序模块,然后将其内容作为类初始化参数传递:

问题是如果您有一个复杂的导入过程,并且要导入多个文件,它可能会开始看起来很凌乱。我最近发现,这种多重初始化参数方法不是’其实是必要的

在Python中,您实际上可以在两个辅助模块(module1和module2)中导入相同的设置加载器模块,而python只会加载一次:

现在,当我们在终端中对此进行测试时:

尽管打电话 进口 设定_loader  两次,Python实际上只调用了一次。这是非常有用的,但是如果您实际上想两次导入文件,也可能引起头痛。如果是这样,那么我会将设置导入器包含在 __在里面__()  每个ClassX实例化两次。

在您的代码中模拟出API调用

使用任何积极开发的(python)编码项目,您都可以’re和您的团队每周将进行数百次相同的测试。如果有’向那里的任何第三方资源发出HTTP请求,这可能会导致问题。 API调用可能是一种支出,过多地刮擦同一源可能会导致IP黑名单,并且这些调用可能会减慢整个测试过程的速度,从而给代码部署过程增加了额外的负担。

为了解决这个问题,我们可以使用Python’的模拟库。模拟对于创建伪函数调用,伪类和其他可以返回伪值的伪对象非常有用。在大多数情况下,测试实际上是在测试应用程序如何解析数据,而不是第三方服务的可靠性。 API’的响应通常是相同的。模拟可以让您模拟API’响应并解析其数据,而不必每次都真正拨打电话。

It’设置起来非常棘手,所以我想我会写一个教程。情况设置有几个组成部分,但我’我会尽量解释一下。让’s说有一个提供一些有用的API响应的服务。那里’是一个由肯尼斯·雷茨(Kenneth Reitz)设置的网站HTTPBin,用于测试HTTP库,我们将在这里使用它。查看: //httpbin.org/ip。内容如下:

让’s说我们的程序想获取IP地址中的 起源 field. Yup –一个毫无意义的程序,但这类似于您的许多情况’ll encounter.

这里’是一个完全过度设计的类,无法从此服务获取数据。在类中初始化时 __在里面__,它将创建一个指向HTTPBin的base_url变量。主要的处理程序功能是 得到_ip 功能,只是抓住了那个领域’的内容。首先拨打 api_call 使用 请求.get 获取该HTTP数据。

要简单地运行此代码(在Python Shell中):

如果我们要模拟出来怎么办 请求.get? Mock模块文档尚不清楚如何在类中定位特定功能。事实证明,最简单的方法不是 魔术模拟 要么 返回_value 而是使用反直觉的命名“副作用”特征。这是测试模块的预模拟:

如您所见,这是一组标准测试,用于检查 ip_grabber 函数返回有效的IP地址。它运行如下:

但是,这里的问题在于,每次运行测试时,它将调用实际的API。为了阻止这个,让’集成了模拟模块:

这里 we’ve:

  1. 导入了模拟模块。注意:如果您收到有关“wraps” in the “six”则几乎可以肯定是因为您安装了六个或模拟安装了一个以上,并且需要删除一个。
  2. 创建一个假函数 fake_get to replace 请求.get 用。这实际上只是返回“123”现在,您可以在下面查看它如何使测试失败。
  3. 在test_ip_grabber函数周围添加了mock.patch包装器。这里非常重要的是指定函数名,因为它是在my_module中导入的,而不是在Python标准库中出现的;即我们正在做“my_module.get” rather than “requests.get”. The 副作用 = 然后说用我们想要的任何功能替换它。
  4. 现在必须将副作用指定的伪造函数添加为该函数的参数。

运行此,我们得到:

嘲笑’s 副作用 已取代 请求.get -要通过此操作,只需更换  返回 {'起源': '123'} with 返回 {'起源': '123.123.123.123'}  and run again:

测试通过和零HTTP流量! --

修复ifup / ifup-eth中的Django / Vagrant错误

我通常使用本地无业游民实例测试django项目。 Vagrant创建了一个运行django项目的虚拟机,该虚拟机可立即识别代码更改。但是,我最近正在运行测试,因此VM突然开始输出错误消息,如下所示。注意:我’已编辑这些终端输出的某些部分。

(滚动到这篇文章的底部以跳至解决方案)

没有翻译文件?一世’我从来没有听说过他们。认为这可能是一个随机错误,因此我尝试再次运行测试并得到:

我尝试注销实例,但遇到I / O错误:

尝试再次ssh进入VM:

有时“关闭并重新打开”解决方案可以工作,所以让’s尝试流浪者重装:

此轮超时错误。该错误似乎与身份验证有关,但它’并非全部。尽管未正确设置,但VM仍根据全局状态运行,这有点奇怪。

我也跑了 名为VirtualBox的GUI 有时对于可视化笔记本电脑上的所有VM十分方便。检查那里,它似乎也存在–所以全局状态’t lying to us. Let’s try halting it:

这次强制关闭。到目前为止,调试此错误是’不好完全奇怪,因为VM事先运行良好。在产生相同的超时后流浪汉:

让’尝试完全销毁无业游民的实例….

从头开始:

那’这是一个非常奇怪的错误。也许某些事情随机失败了?

显然,它仍然创建了VM。 SSH进入它可以做到这一点:

奇怪的是没有文件!还是有东西’t startup properly.

在这一点上,我有点沮丧,并开始向Google询问错误。我可以找到的最相关的博客文章是Mike Berggren’s solution here: http://mikeberggren.com/post/100289806126/if-up。他解决了这个问题并报告:“我会为您省去其余的细节,但足以说明这一点,我们最终绕过了该检查并从主机运行了相同的命令。它返回了另一个声称拥有所有权的MAC地址“。这是否意味着他从字面上注释掉了进行检查的代码行?他可能遇到了非常不同的问题,而我’我不是开发人员专家,但也许在那里’s a better solution –也许那张支票是有原因的。

让’回顾一下前面提到的网络错误:

删除流浪者文件,并显示相同的IP地址。这意味着该特定的无业游民总是被分配该IP地址。如果这是唯一的实例,那么该虚拟网络上的其他对象正在使用它吗?我的mac电脑内部存在某些问题。

我们可以检查一下’通过检查正在运行的进程来真正运行(除了global-status和VirtualBox所说的那样):

啊哈!实际上有两个。让’销毁我们之前创建的无法运行的空白虚拟机,并查看是否有任何更改:

是的,它已经消失了:

使用kill -9 [pid]删除它。

现在让 ’尝试重新创建VM:

有用!

结论:

  • I’我仍然不确定为什么会首先发生这种情况。一开始的错误完全是突然的– I’d已在该虚拟机上运行了几周而没有任何问题。也许事实是我’d已经运行了这么长时间?
  • 流浪汉的全局状态和VirtualBox似乎不能完全准确地报告正在运行的虚拟机,因此绝对可以使用ps检查所有正在运行的vbox进程,并删除没有’t正确关闭。这让我想起了–全局状态下的修剪选项(//www.vagrantup.com/docs/cli/global-status.html),它可以修复持久性旧条目。

非常感谢Tony(http://blog.tonns.org/)以帮助解决此问题!

将MongoDB的findOne()功能扩展到findAnother()

给定一个可以使用的新MongoDB实例,通常很难理解其结构,因为与SQL不同,该数据库本质上没有架构。流行的初始工具是 Variety.js,它会找到所有可能的字段,并告诉您它们在数据库中的类型,出现的百分比。

但是,通常也可以查看字段的内容。为此,您可以使用 找One(),它从集合中获取似乎是最后插入的记录,并将其漂亮地打印到终端。很好,但是有时您希望查看多个记录,以更好地了解字段内容。在这篇文章中,我’将向您展示我如何扩展Mongo来做到这一点。

(假设你’ve已经安装了mongo和git– I use  酿造 安装 蒙哥 from the 自制程序包管理器 和git随附Mac上的XCode)

首先,让’s获得mongo的副本’s code:

这将在您的文档中创建一个文件夹,所以让’s inspect it:

那里’那里有很多文件,需要一段时间才能找到findOne()函数的位置。 Github’的存储库搜索返回太多结果,因此让’而是使用unix文件搜索。 MongoDB用JavaScript编写(并已编译),因此我们需要查找类似 找One = 功能( or 功能 找One( . Try this search:

这两个标志是 -l  (小写的L)显示文件名,以及 R  搜索所有子目录。最后的句号表示搜索当前目录。您可以看到它在其中找到了一个javascript文件,“collection.js”。如果在文本编辑器中打开它,则会列出findOne()函数:

此代码也可以在mongodb github页面上找到: //github.com/mongodb/mongo/blob/master/src/mongo/shell/collection.js#L207

我们的功能将扩展findOne而不是查找另一条记录。这可以通过执行“find”使用完全相同的代码,但随后跳过随机的记录数。跳过量必须小于列出的记录数,不幸的是,这意味着我们必须运行两次查询。首先计算结果的数量,其次实际跳过一些数量。

复制findOne函数并将其重命名为findAnother,而将这些行放在顶部:

  1. 获取查询返回的记录数(存储在total_records中)
  2. 生成一个介于1到计数之间的随机数(存储在randomNumber中)
  3. 再次使用该数字作为跳过查询(存储在光标中)

在JavaScript中生成范围内的随机数有点晦涩难懂,但我在StackOverflow上找到了一个有用的技巧来做到这一点: http://stackoverflow.com/a/7228322 in one line. I’m used to Python’s ultra simple 随机.randrange().

让’首先测试一下。您’我会注意到所有代码都可以在mongo中返回’s javascript shell:

您实际上可以在终端中实时替换此代码,尽管它赢得了’关闭后将无法保存。尝试首先用Hello World替换findOne:

您可以先在终端中通过复制第一个等号之后的所有内容来测试我们的新功能。打开mongoDB shell到您喜欢的数据库并输入 D b.我的收藏.找One =  然后粘贴功能。尝试调用它,它每次应返回不同的结果。

让’的补丁mongodb现在具有我们的功能。我们必须从刚刚下载的源代码编译mongo。

  1. 使用新的findAnother()函数保存刚编辑的collection.js文件
  2. 确保已安装C ++编译器。一世’m使用gcc(已使用安装)  酿造 安装 海湾合作委员会
  3. 检查您的处理器有多少个内核。根据Google的说法,我的2.7 GHz Intel i5有4个内核。
  4. 在同一终端窗口中(仍在mongo文件夹中),键入: 坏话 -j4 蒙哥  and press enter. The 4  这是我拥有的核心数量,并会认真加快速度。 坏话  是一个处理编译, 蒙哥  最后,这表明我们只想修补mongo’s client.

您’当scons检查所有内容时,会看到大量绿色文本,然后:

它编译了!现在,我们必须用修改后的版本替换现有的mongo应用程序。让’s do a unix find:

我们要替换/ usr / local / Cellar /中的mongo应用程序(brew安装到的位置)。让’将其备份,然后复制:

现在,打开一个MongoDB shell到您喜欢的数据库:

 Caveats:

  • 这可能真的很慢,因为它必须运行两次查询。但是,通常我不’t将超级征税查询添加到findOne()。
  • 如果使用brew重新安装/升级mongo,则可能会替换此功能–他们相当频繁地发布新版本。

改进措施

  • 该函数的作用类似于python生成器,保持状态并向前循环直到到达记录集的末尾。这将解决上面的任何缓慢问题,但随机性会降低。

将HTML表转换为Excel下载HTTP响应:慢速OLAP DB连接的黑客

总览

善科 (“Good fox”日本)是一个报告系统(在这里查看Github上的代码) 一世’是在过去两周内在Mozilla创建的。基本上,我的非技术同事对Tableau感到非常沮丧(“INNER JOIN和OUTER JOIN有什么区别?”),我决定为他们创建一个简单的仪表板界面。

它是一个简单的引导程序前端,它包含数据库的活动统计信息 赞助瓷砖。您可以深入查看每个图块或客户/合作伙伴,并按区域设置,国家/地区和日期进行透视。

善科’s堆栈(从高到低)

一项新功能

加载分析页面之一时,将显示一个表格。我的同事希望能够将数据下载到Excel。我想出了4种可能的方法来实现此目的:

  1. 只需重新运行查询,在后端将结果格式设置为csv,然后将其保存并在window.open()文件位置即可。
  2. 自动保存每个分析请求服务器请求中的数据,并定期清除旧文件。
  3. 使用像 ExcelBuilder
  4. 将数据发送回服务器,对其进行格式化,然后通过iframe返回给客户端

哪个是最佳解决方案?

  1. 这是有问题的,因为我们的重点是查询速度。 redshift数据库是一个 OLAP面向列的数据库和仅追加。这意味着添加数据的速度非常快,但是查询速度却很慢(通常超过6秒)。是的,它正在处理数十亿行这样令人难解的行,但是就等待这么长时间的用户体验而言并不是那么好。 ’如果他们已经有数据,则要再等待6秒钟重新运行分析。
  2. 听起来这可能最终会在客户端上存储大量数据,但是效果很好。在安全性方面,我’我不确定数据应该留在用户身上’不需要PC。
  3. 这没有’t work out so well –在Firefox中,文件命名错误。将来,我’d根据分析参数命名文件,例如<client>-<date>-<country>.xls
  4. 这是最怪异的解决方案,但是它有效! Flask在本地运行,因此运行速度非常快。具有文件许可权的JQuery / JavaScript并不会带来很多麻烦,而且您可以在服务器上轻松地操纵数据这一事实也很不错。

解决方案4

该过程如下“Download for Excel” button is clicked:

  1. 使用JavaScript引用HTML表并将其转换为数组数组
  2. 将iframe附加到DOM
  3. 将带有POST操作和隐藏字段的表单附加到iframe
  4. 将表内容插入隐藏字段’s value
  5. 提交表格
  6. 让 Flask receive the POST request and format the information as a CSV
  7. 返回带有包含CSV的文件附件的HTTP响应

让’s implement it

那里 were various ways to do this in JQuery with 可重复的.()  但我遇到了麻烦,仅使用.children引用细胞就容易得多。

然后,(本地运行中的)Flask将在以下位置接收POST请求: /download_excel . Let’s set up the route:

现在,当用户单击按钮时:

下载Excel链接

他们立即得到:

下载弹出窗口

对不起,我可以’无法显示Excel中的数据,因为数据不是’目前还没有公开。所有代码均可用 在github上!

然而,一件奇怪的事情是表格没有’t出现在检查器中(在Chrome或Firefox中):

在检查器中不可见

不过,您可以使用一些相当长的吸气剂来访问它:

why.jpg

未来功能 

  • 这些文件的名称可能比data.csv更直观–可能是网址中出现的各种情况的组合’s query string
  • 可容纳超过6行的表格。使用不同的定界符(例如,“###”.
  • 如果有好处,请创建一个.xls文件而不是CSV文件

在Firefox扩展中使用Web Worker

Web Worker允许您在诸如Firefox之类的浏览器中在后台运行代码。这是将其构建到Firefox扩展中的方法,这与在页面上正常创建一个扩展略有不同。这样做的文档基本上不存在,所以希望您’ll find this useful.

请确保您具有与开发环境相似的开发环境 在我以前的帖子中描述过。

工人如何工作?

  • / data /中的工作程序未直接连接到/ lib /中的脚本
  • 但是,他们可以通过相互发送消息进行通信
  • 这些消息仅是文本,因此可以包含序列化的JSON,但仅此而已
  • 您’下面会注意到,我们基本上只是在两个脚本之间添加消息

工人的代码

导航到/ data /目录并创建一个名为hello_world.js的文件

现在在其中粘贴以下内容(vim的新用户,请按 i  to start typing and Esc键  followed by :q  to save):

这就是说,只要工作人员从客户端收到一条消息,然后将消息发送回“Hello” prepended.

这里的一个注意事项:在工人中,您可以’使用有用的功能  安慰.日志(“信息”) , instead use  倾倒(“信息”)

让’从主代码中调用工人

让’导航回到 /LIB/  folder and edit the 主要.js  文件,这是在扩展程序中运行的第一件事。

粘贴以下代码:

然后跑  cfx  . You’会发现一个混乱的错误:

啊哈!这里的关键是:  ReferenceError: 工人 定义的 。这是因为Firefox扩展程序改用了ChromeWorker。我们需要将其粘贴在main.js中,方法是将其粘贴在顶部:

并将引用hello_world.js文件的行更改为调用ChromeWorker:

好吧让’尝试再次运行它!尝试  cfx  。 WTF另一个错误?

这里的关键是:  格式错误 脚本 URI: 你好世界.js 。此隐秘错误是因为Firefox可以’尚未访问 /数据/  夹。我们必须使用SDK的另一部分来启用对其的访问。

打开 主要.js  并将其放在顶部:

现在我们可以使用该功能 .数据.网址() 。当您将文件名作为第一个参数时,它将返回一个字符串,例如  资源://jid1-zmowxggdley0aa-at-jetpack/test/data/whatever_file.js 在扩展名的情况下正确地引用它。修改工作程序导入行,如下所示:

现在让 ’使用以下命令再次运行扩展程序 cfx  :

是的,它有效!工人退回了消息“您好 Matthew“.

常问问题

  • 这是什么 {符号}  mean?

它的简写为:

基本上这意味着  要求(“铬”) 返回一个Object,我们只需要键引用的值“ChromeWorker”。这是从JavaScript对象提取内容的非常简洁的方式,将来会派上用场。

  • 为什么现在将Worker称为ChromeWorker?我们在用Google Chrome做些什么吗?

这是一个命名巧合,与浏览器中的Chrome无关。在这种情况下,Chrome指的是Firefox插件内部。

设置Firefox扩展的开发环境。

这是我用来创建简单的Firefox扩展的方法。本教程是t的前身他的下一篇关于使用Web Workers (即允许代码在后台线程上运行)。

搭建环境

We’将需要Firefox插件SDK。这是python文件的集合,可让您运行测试版(可选为空白)的Firefox。要下载它:

现在解压缩并删除压缩包:

转到目录并启动特殊的shell:

现在您可以看到shell已经在提示的括号中添加了(addon-sdk-1.17)。这意味着该窗口可能是文本的一半,因此我们可以使用以下命令来减少该文本:

干净得多! --

设置扩展模板

现在我们有了这个特殊的addon-sdk shell,导航回到您的文档并为我们的扩展程序创建一个新文件夹。

这个特殊的shell包含各种有用的命令,它们看起来都像  cfx y 。有关他们的更多信息,请参见 这里。在这种情况下,我们使用  cfx 在里面

让’检查创建的内容:

  •  LIB  包含一个名为 主要.js  这是所有扩展代码的主要处理程序文件
  • 数据  为空,但可用于存储工作程序(我们将在后面介绍)或大数据文件等内容
  • 测试  可以包含单元测试(很难设置,但对以后的测试驱动开发很有用)
  • .json  包含有关扩展的元数据–版本号,创建者名称,描述,许可等

您可以开始在main.js中编写代码,它将在浏览器中运行。完成后,使用  cfx  to test it!

请参阅下一个教程,了解如何使用网络工作者编写firefox扩展!