AQL:用于存储库的综合查询语言
我们在JFrog的一个信条是,我们是社区驱动的。在每次路线图会议上,我们都会讨论行业趋势中出现的功能,以及我们经常从Artifactory社区获得的功能请求。AQL就是这样一个特性。没有人说:“嘿,伙计们,你们为什么不构建一种超级高效的查询语言,可以在我们的存储库中找到任何东西,并利用我们的数据库架构,这样它就会是Artifactory独有的,其他人无法做到。”但实际情况是,我们不断收到执行不同搜索功能的REST API调用的变体请求。一个典型的例子是根据创建日期搜索工件。在2.2版本中,我们发布了在日期范围内创建的工件。这个REST API调用查找在您指定的日期范围内创建的工件。但后来,在越来越多的请求要求能够按日期搜索,但在不同的领域,我们发布在日期范围中具有日期的工件在3.2版本中。因此,现在您可以根据创建、修改或下载的时间来搜索工件。您可以看到类似的场景基于布局的工件最新版本搜索发布于2.6版本,之后是基于属性的工件最新版本搜索在3.1.1版发布。还有更多的例子,API调用被更多的参数和选项修饰。最终我们意识到你可以在某些时候取悦一些人,但无论我们多么想让我们的社区满意,我们都无法预测每个人都需要的所有不同功能。无论我们添加什么增强功能,总会有人需要其他功能。
赋予权力的礼物
你知道那句古老的谚语授人以鱼vs.授人以鱼?我们认为,正确的方法不是不断地“提供新的api”来满足越来越多的搜索需求,而是让社区有能力构建任何你能想到的搜索查询,从而……人工查询语言诞生了。
这就是AQL的精髓。通过提供这样一种极其灵活的语言,允许您指定任意数量的搜索条件,在任何逻辑配置中组合,使用任何过滤器集并显示任何输出字段集,我们不仅可以满足我们已经收到的任何请求,还可以满足任何人做梦都没有想到的任何未来请求。
见分晓
让我们看看AQL的实际应用,看看现实世界的例子。
示例1
乔治见面。
George是DevOps经理。
乔治今天不高兴。他的开发人员抱怨系统变得迟钝,并且被许多旧的未使用的工件弄得乱七八糟,他们侮辱地称之为“垃圾”,但是硬件升级目前对George来说不是一个选择。
是春季大扫除的时候了。特别是从远程存储库缓存中,大型工件可以一直存在。我们真的需要这么大的数据量吗?
首先我们去找旧的藏物,那些创建于一年前(假设今天是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"}]},{"分配”:“可靠的”},{“stat.downloaded”:{" $ gt ": " 1000 "}}]})
由于很难在这样的单行代码中遵循查询逻辑,因此下面是将相同的查询分散在几行中并适当缩进:
物品。查找({" $和":[{" $或":[{"@deb。架构":"i386"}, {"@deb。架构":"amd64"}]}, {"分发":"可信"},{"统计。下载":{"$gt":"1000"}}]})
狗粮味道很好。
在JFrog,我们的座右铭是“吃自己的狗粮”。我们使用Artifactory继续开发Artifactory,我们通过Bintray分发Artifactory,现在我们很高兴在两个项目中使用AQL。我们使用它来实现清理策略,查找非常具体的工件,甚至根据不同的属性找到非常具体的模块子集,以便用一个相对简单的查询来为Bintray组装一个构建,从而减少了80%的脚本编写。而这只是无限的冰山一角。AQL的设计非常灵活,可以满足您在可预见的将来可能想到的任何搜索需求。想想所有可以用AQL查询结果填充的很酷的仪表板。
事实上,我们非常有信心AQL可以满足您的需求,因此我们将举行AQL挑战,并挑战您为我们提供AQL无法处理的搜索场景。请继续关注,尽你最大的努力。