AQL:一种针对存储库的综合查询语言

我们JFrog的信条之一是我们是社区驱动的。在每次路线图会议上,我们讨论由行业趋势产生的特性,以及我们经常从Artifactory社区获得的特性请求。AQL就是这样一个特性。没有人说:“嘿,伙计们,你们为什么不建立一种超级高效的查询语言,它可以在我们的存储库中找到任何东西,并利用我们的数据库架构,这样它将是Artifactory唯一的,没有人可以做。”但确实发生的情况是,我们不断收到请求,要求对执行不同搜索功能的REST API调用进行更改。一个经典的例子是通过创建日期搜索工件。在2.2版本中,我们发布了在日期范围内创建的工件.这个REST API调用查找在您指定的日期范围内创建的构件。但后来,在收到越来越多的请求要求按日期搜索的能力,但在不同的领域,我们发布了日期在日期范围内的工件在3.2版本中。所以现在您可以根据构件的创建、修改或下载时间来搜索它们。你可以看到类似的场景基于布局的工件最新版本搜索在2.6版本中发布,随后是基于属性的工件最新版本搜索在3.1.1版发布。还有更多使用更多参数和选项修饰API调用的例子。最终我们意识到你有时可以取悦一些人,但无论我们多么想让我们的社区满意,我们都无法预测每个人都需要的所有不同功能。无论我们添加什么增强功能,总会有人需要其他东西。

授权的天赋
你知道那句古老的谚语给人鱼vs.教他钓鱼?我们决定,正确的方法不是不断地“提供新的api”来满足越来越多的搜索需求,而是赋予社区能力,使其能够构建您集体想象中能够想到的任何搜索查询,因此……Artifactory查询语言诞生了。

这就是AQL的本质。通过提供这样一种极其灵活的语言,允许您指定任意数量的搜索条件,以任意逻辑配置组合,使用任意一组过滤器并显示任意一组输出字段,我们不仅可以满足我们曾经收到的任何请求,还可以满足任何人都没有想到的任何未来的请求。

检验在布丁里
因此,让我们来看看AQL的实际应用,并看看真实的例子。

示例1Artifactory可以在树莓派上运行。

乔治见面。
George是一位DevOps经理。
乔治今天不高兴。他的开发人员抱怨说,系统变得越来越迟钝,而且充斥着许多旧的未使用的工件,他们侮辱地称之为“垃圾”,但硬件升级目前对George来说不是一个选择。
春季大扫除的时间到了。特别是从远程存储库缓存中,大型工件可以一直存在。我们真的需要这么多tb的数据吗?

首先我们要找到古老的藏物,那些创作于一年多以前(假设今天是2015年5月18日)。这在AQL中很简单:

物品。找到({“类型”:“文件”、“创建”:{$ lt:“2014 - 05 - 18 - t}})

注意我们如何使用比较运算符,比如"$ lt我们利用了AQL中默认的内置功能,即使用“$and”组合多个标准。

但就像我奶奶常说的,“老并不一定意味着无用。”让我们确保不删除任何仍在使用的工件。乔治只想删除一些过去六个月都没被下载过.所以让我们为我们的查询添加另一个条件,这次使用“stat”域中的“downloads”字段:

物品。找到({“类型”:“文件”、“创建”:{$ lt:“2014 - 05 - 18 - t”},“stat.downloaded”:{$ lt:“2014 - 11 - 18 - t}})

但由于墨菲潜伏在每个角落,乔治想要确保没有重要的东西被删除,所以他会删除跳过“释放”存储库

物品。找到({“类型”:“文件”、“创建”:{$ lt:“2014 - 05 - 18 - t”},“stat.downloaded”:{$ lt:“2014 - 11 - 18 - t”},“回购”:{" $ nmatch”:“* *”发布}})

在这里,我们添加了一个标准,即存储库名称不包含模式“*release*”。请注意,如果您的任何存储库的名称中有“release”——但它不是一个发布存储库……它也将被跳过,您可能需要重新考虑您的命名约定。

为了让这个例子更复杂,假设乔治也想限制自己到大于1000字节的“大”工件

下面是最终的AQL查询,它可以找到系统中满足所有这些标准的所有工件:

物品。找到({“类型”:“文件”、“创建”:{$ lt:“2014 - 05 - 18 - t”},“stat.downloaded”:{$ lt:“2014 - 11 - 18 - t”},“回购”:{" $ nmatch”:“* *发布”},“大小”:{" $ gt ": " 1000 "}})

如果你还没有流口水,让我们再看一个例子。Debian是一个很好的主题,因为它涉及到体系结构、组件和分发,这是很好的可搜索材料,但类似的场景也可以出现在YUM、npm和几乎任何其他类型的组件上。

示例2

让我们找到所有的Debian组件

  • 在“可信”分布中
  • 下载超过1000次
  • 并且连接到amd64或i386架构

我建议您使用传统的搜索工具来查找这些组件

使用AQL就容易多了。

items.find({”和“美元:[{”或“美元:[{”@deb。架构":"i386"},{"@deb。架构”:“amd64”}]},{”@deb。分配”:“可靠的”},{“stat.downloaded”:{" $ gt ": " 1000 "}}]})

由于在这样的一行代码中很难遵循查询逻辑,下面是相同的查询分散在几行代码中并适当缩进:

物品。查找({" $和":[{" $或":[{"@deb。架构":"i386"}, {"@deb。架构":"amd64"}]}, {"@deb。分布":"可靠的"},{"stat。下载":{"$gt":"1000"}}]})

狗粮味道很好。
在JFrog,我们靠的是“吃自己的狗粮”。我们使用Artifactory继续开发Artifactory,我们通过Bintray分发Artifactory,现在我们很高兴在两个项目中使用AQL。我们使用它来实现清理策略,搜寻非常特定的工件,甚至根据不同的属性找到非常特定的模块子集,以便用一个相对简单的查询为Bintray组装一个构建,减少了80%的脚本编写。而这只是无尽的冰山一角。AQL的设计非常灵活,它可以满足您在可预见的未来可能想到的任何搜索需求。您可以用AQL查询的结果填充所有很酷的仪表板。
由AQL填充的仪表板
事实上,我们非常确信AQL可以满足您的需求,所以我们将举行一个AQL挑战,并挑战您提供给我们一个AQL无法处理的搜索场景。继续关注,尽你最大的努力。