Skip to content

AQL

AQL(Alf Query Language)是 档友会 DocEase 内容管理平台所使用的一种查询语言,专门设计用于查询和管理存储在 DocEase 内容仓库中的对象。AQL 类似于 SQL,但在语法和功能上有所区别,以适应 DocEase 特有的对象模型和内容管理需求。

目前 AQL 支持的功能如下:

功能集是否支持?
select
update
insert
delete
子查询
函数有限支持

主要特点和用途

  • 对象查询:AQL 允许用户根据对象的属性、类型、关系等条件进行查询。例如,可以查询某个文件夹下的所有文档,或者查找具有特定标签的所有对象。
  • 属性选择:可以指定返回的对象属性,类似于 SQL 中的 SELECT 语句。例如,只选择文档的名称和创建日期。
  • 条件过滤:支持使用 WHERE 子句来定义查询条件,例如,可以根据文档的创建日期、修改日期、作者等属性进行筛选。
  • 排序:可以通过 ORDER BY 子句对查询结果进行排序,支持升序和降序排列。
  • 分组和聚合:支持使用 GROUP BY 和聚合函数(如 COUNT, SUM, AVG 等)来对查询结果进行分组和统计。

示例

以下是一些常见的 AQL 查询示例:

查询特定文件夹下的所有文档:
SELECT * FROM cm:content WHERE PARENT('/MyFolder')

查询创建日期在某段时间内的所有文档:
SELECT * FROM cm:content WHERE RANGE(cm:created, '[2023-01-01...2023-12-31]')

检索引擎的选择

针对同一个aql,可指定查询所使用的引擎,除非显式指定 FFS ,默认情况下将使用FTS。

引擎特性如下表:

搜索引擎介绍
FTS说明:默认使用全文搜索系统,请确保ES已开启,并且在ACS中正确配置地址与账户。
优点
全局高速搜索,精度高,速度快;
支持全文搜索,通过text(string)函数来指定;
支持高亮;
支持聚合;
支持ff排序字段;
支持指定文件夹的深度查询搜索;
可指定精确类型(通过在类型后添加_exact来指定,将不包含子类)进行搜索;
可指定撇除类型(通过在类型前添加_来指定撇除)进行搜索。
缺点
以下情况下的索引可能会有延迟:
- 深度复制一个文件夹,该文件夹下的所有子节点将会被延迟索引(出于性能考虑);
- 将一个对象移动到回收站,则该对象将延迟出现在回收站中。
FFS说明:文件系统搜索引擎(FILE-FOLDER-SEARCHER),默认不开启。
可通过在在aql末尾显式指定(using ffs,不区分大小写)来开启使用该引擎。
该引擎能保证实时性,但是在不指定搜索路径时性能极差,适合作为小范围的精确搜索使用(如文件夹树、文件列表等)。
部分搜索条件可能不被支持。
优点
超即时性,任何对象的变更能立即被搜索到。
缺点
不建议全局搜索,性能会受到很大影响;
排序速度很慢且消耗大量系统资源,不建议作为高频的列表搜索首选引擎;
不支持全文搜索;
部分条件函数不被支持;
无法指定特定类型(即_exact后缀无效);
无法撇除类型(即_前缀无效)。

示例

使用FTS

sql
select ... from ... order by ... limit ...

使用FFS

sql
select ... from ... order by ... limit ... using ffs

通过在末尾添加启用短语using ffs即可开启ffs引擎,大小写不敏感。

使用archive搜索

sql
select ... from ... order by ... limit ... using ffs,archive
select ... from ... order by ... limit ...

通过指定archive域来启用回收站搜索,只针对ffs生效,FTS引擎下默认可直接进行archive查询

建议:回收站查询添加sys:archivedBy='xxx'条件来加速节点过滤。

如何查询某个用户下的回收站内容?

sql
//先查到该用户的回收站对象,获取ID
select cm:name, ID from sys:archiveUser where cm:name='admin'

//之后通过该ID即可获取该用户回收站下的对象列表
select cm:name, TYPE, ID from cm:folder..cm:content where parent('941aa6bd-051d-4b11-b577-c7da2c099d47') order by ff, cm:name

AQL规则

字段

AQL支持部分特殊字段(如ID等字段)的查询。 注意:部分字段只支持select,不支持条件与排序,支持情况如下表。

分类字段支持select支持where支持order by说明
计算字段ID是(FTS)sys:node-uuid的默认别名,注意必须全部大写
TYPE类型,如cm:folder
ASPECTS切面,返回一个set,包含该节点所拥有的切面
CATEGORY对象类型,如FOLDERDOCUMENT
PERMISSIONS权限列表,返回一个set
SIZE是(FTS)是(FTS)对象内容大小,只针对cm:content属性
EXTENSION对象的扩展名,只针对cm:content属性
USER_ENABLED当前用户是否可以使用,只有在查询用户时有用
特殊@ATTRS对象的所有属性
属性cm:name, cm:title 等对象的属性,如是多值属性,则返回一个list
排序ff默认文件夹会排前面。如果指定desc则文件排前面。

select [columns]

通过select指定需要查询的结果集字段。

select *表明搜索对象的所有字段,也同时包括计算字段诸如TYPE ASPECTS CATEGORY PERMISSIONS SIZE EXTENSION

通过elect @ATTRS来选取对象所有属性,不包括任何计算字段。

from [type]

AQL支持的表有两种类型,针对不同类型的表所支持的并行查询数都有不同限制。

  • 对象类型表,一般有cm:cmobject cm:content cm:folder等常用类型与各种自定义类型,AQL支持多表并行查询,使用select xxx from type1..type2_EXACT.._type3 where xxx的方式指定多个类型,类型之间使用双点..进行连接,在FTS模式下额外支持任意类型的精确指定与撇除。
    • 精确类型:通过在类型后添加_EXACT后缀来开启,大小写不敏感
    • 撇除类型:通过在类型前添加_前缀来开启
  • 特殊表,形如audit等特殊类型,不支持多表查询,如果通过..的方式连接表,将会导致搜索引擎启用对象查询,可能会报错或者查询到错误的结果。

通过from type来指定需要查询的对象类型。

通过from type_exact的显式后缀来强制指定该类型(不包含子类),该后缀大小写不敏感。

通过from xxx.._type的显式前缀来强制撇除该类型(包含子类)。

注意:FFS引擎不支持精确类型与类型撇除,该模式下_exact后缀与_前缀将会失效。

where [condition]

支持的操作符

操作符示例说明
=where... cm:name='abc'完全匹配
like/not likewhere... cm:name like 'abc%'
where... cm:name not like 'abc%'
模糊匹配,支持?%的模糊匹配符
<>/!=where... cm:name<>'abc'
where... cm:name!='abc'
不匹配
</>/<=/>=where... cm:starCnt>=100范围匹配
is null/is not null判断是否为空值
is true/is not true判断是否为真值
in/not inwhere ID in ('id1', 'id2')
where ID not in ('id1', 'id2')
列表匹配,FFS引擎不支持

支持的函数

所有函数都大小写不敏感

函数示例说明
has_aspect(string)where... has_aspect('cm:titled')拥有切面
has_no_aspect(string)where... has_no_aspect('cm:titled')不拥有切面
has_tag(string)where... has_tag('旅游')拥有标签,FFS引擎不支持
has_no_tag(string)where... has_no_tag('旅游')不拥有标签,FFS引擎不支持
text(string)where... text('文本')文档内容查找,FFS引擎不支持
parent(string, [bool])where... parent('id')
where... parent('/abc', true)
where... parent('TEST_GROUP', true)
指定搜索范围,第一个参数可填父对象的id路径组名,第二个参数表示是否级联搜索,默认值为false
注意:FFS最多支持一个parent函数条件
not_parent(string, [bool])where... not_parent('id')
where... not_parent('/abc', true)
where... not_parent('TEST_GROUP', true)
排除搜索范围,参数同上,FFS引擎不支持
range(string, string)where... range(cm:count, '[0...10)')
where... range(cm:created, '[2021-01-01...2021-01-02]')
指定区间,通过[ ( ] ) 来指定开闭区间([]表示包含边界值 ()表示不包含边界值),fromto之间用...进行间隔即可。注意:如果使用日期类型,则下文的日期格式才能被支持

支持的日期格式

在条件中使用日期需要先进行转化,支持的日期格式如下:

支持的日期格式
yyyy-MM-dd'T'HH:mm:ss.SSSZ
yyyy-MM-dd'T'HH:mm:ss.SSS
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mmZ
yyyy-MM-dd'T'HH:mm
yyyy-MM-dd'T'HHZ
yyyy-MM-dd'T'HH
yyyy-MM-dd'T'Z
yyyy-MM-dd'T'
yyyy-MM-ddZ
yyyy-MM-dd
yyyy-MMZ
yyyy-MM
yyyy-MMM-dd'T'HH:mm:ss.SSSZ
yyyy-MMM-dd'T'HH:mm:ss.SSS
yyyy-MMM-dd'T'HH:mm:ssZ
yyyy-MMM-dd'T'HH:mm:ss
yyyy-MMM-dd'T'HH:mmZ
yyyy-MMM-dd'T'HH:mm
yyyy-MMM-dd'T'HHZ
yyyy-MMM-dd'T'HH
yyyy-MMM-dd'T'Z
yyyy-MMM-dd'T'
yyyy-MMM-ddZ
yyyy-MMM-dd
yyyy-MMMZ
yyyy-MMM
yyyyZ
yyyy

order by [fields]

支持通过属性进行排序,示例:

... order by cm:name, cm:modified desc

注意:在FTS/FFS模式下,支持ff字段的排序。

ff字段是file-folder的简称,默认将以文件夹 > 文件的顺序进行优先排序。

如果选择desc倒序,则将以文件 > 文件夹的顺序进行优先排序。

limit [[skip, ] size]

该功能与mysql-sql一样,不再赘述。

如何最小开销获取总数值?

只需要使用limit 0即可在不返回具体数据行的前提下获取符合条件的总数据量,在某些计数场景下可以最大化优化性能。

国际化字段的支持

对形如cm:title, cm:description等国际化字段,搜索规则与限制如下:

  1. 仅支持= <> != like not like is null is not null操作符
  2. 将会匹配任何语言对应的值

在AFC中使用AQL

AFC的搜索模块除了提供针对aql的支持外,还额外提供了诸如高亮聚合等功能,可以最大程度上个性化查询行为。

检索

通过对aql的封装,执行查询,并遍历结果集。

java
String aql = "select cm:name, cm:title from cm:cmobject where cm:title not like '数据字典' limit 20";

IAfCollection<IAfCollectionRow> coll = new AfQuery(aql).execute(afSession);
while (coll.next()) {
    System.out.println(coll.row().getRaw());
}

System.out.println("total>>>" + coll.getTotal());
coll.close();
// 注意:搜索结果集必须要在使用完毕后显式关闭。

遍历

通过使用while(coll.next())进行遍历。

也可使用for循环进行遍历。

在kotlin中推荐使用forEachThenCloseforEachIndexedThenClose进行遍历,不需要显式关闭结果集。

结果集元数据

通过使用coll.size()来获取当前结果集行数。

通过使用coll.getTotal()来获取当前搜索结果总数。注意:默认情况下total的上限为10000。

在kotlin中可直接使用coll.sizecoll.total属性来获取对应的信息。

游标操作

通过使用coll.absolute(x)来指定当前游标。

通过使用coll.cursor()获取当前游标位置。

在kotlin中可以直接使用cursor属性。

也可以直接使用coll[i]来当作数组获取对应行

获取行数据

通过使用coll.getRow()来获取当前行,需与游标配合使用。

在kotlin中可直接使用row()方法

高亮

java
AfQuery query = new AfQuery("select ID from cm:content_exact where parent('/') and text('业务')");
query.setHighlightOption(new AfHighlightOption().setPreTag("<b>").setPostTag("</b>").setNumOfFragment(1).setPhraseLimit(1));

通过AfQuery类的setHighlightOption方法可设置高亮相关选项,包括:

  • 前后包围标记
  • 返回高亮片段数
  • 返回短语数

注意: 要获取高亮结果,aql中至少需要有一项text全文索引条件。

获取高亮结果

返回的结果集中有HIGHLIGHT字段,该字段的值类型为Map<String, List<String>>

当前仅有唯一key——TEXT,对应为高亮片段列表。

聚合

java
AfQuery query = new AfQuery("select ID from cm:cmobject where parent('/', false) limit 0");
query.setAggs(Arrays.asList(
    new AfTermCountAggregation("标签", "TAG"),
    new AfNumericRangeCountAggregation("文件大小", "SIZE").addRangeOnlyTo("low", 100).addRange("medium", 100, 200).addRangeOnlyFrom("high", 200),
    new AfSumAggregation("sum", "cm:number"),
    new AfDateRangeCountAggregation("TIME", "cm:created")
    .addRangeOnlyTo("last month", ZonedDateTime.parse("2022-05-01T00:00:00+08:00"))
    .addRangeOnlyFrom("this month", ZonedDateTime.parse("2022-05-01T00:00:00+08:00"))
));

IAfCollection<IAfCollectionRow> coll = query.execute(afSession);

for (label in coll.getAggSlotLabels()) {
    coll.getAggSlot(label); //获取聚合结果
}

AFC中支持针对搜索结果集的聚合计算。

coll.aggSlotLabels[kotlin]/coll.getAggSlotLabels()[java]将会返回当前结果集的所有聚合结果槽标签(即声明聚合器时指定的字符串,如上文中的low TIME等),并通过标签获取对应的聚合结果槽slot,根据不同类型的聚合器,slot将对应不同的类型(都基于IAfAggSlot,具体类型在下表中给出)。

注意:聚合器的标签不能互相重复,否则会导致查询失败。

Audit查询

查询审计记录时,可以针对search_keys进行单独的条件查询。

以下aql是一条查询其中objectName的语句:

sql
select search_keys.objectName as name, event_name, user_id from audit where search_keys.objectId='09e5ebb8-81fa-4ca8-a056-6bb03304b51c' and event_name='Attribute' order by gmt_created

audit中可以使用的字段如下:

字段名说明备注
id
user_id操作人
search_keys.x某个具体的查询key,注意必须使用列别名,否则查询的数据会有问题!也可以通过search_keys.a='xxx'的方式进行查询
detail存储的其他字段
event_name事件名称
gmt_created创建时间