Source: https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/dql/clauses/sample/ Documentation version: v5.3.2 # SAMPLE `SAMPLE`子句用于在遍历过程中对边采样。在处理超大数据集时,可通过该子句选取较小且易于处理的样本进行分析。 取决于遍历的方向,`SAMPLE`子句可分为两种类型:向右采样(`SAMPLE RIGHT`)和向左采样(`SAMPLE LEFT`)。目前仅支持向右采样(`SAMPLE RIGHT`)。 在悦数图数据库开发版持久图中,`SAMPLE`子句直接用于`MATCH`语句中的边模式。 ## 使用说明 - 不支持在临时图中使用`SAMPLE`子句。 - `SAMPLE`子句只能写在边模式上,不能写在点模式上。 - `SAMPLE`子句不能用于涉及边匹配的近似最邻近查询。更多信息,请参见[最近邻查询](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/dql/nearest-neighbor/)。 - 若推断得到无向的边类型,则不支持采样。无向边类型的方向声明如下:`~[ edge_pattern_filler ]~`。更多信息,请参见 [CREATE GRAPH TYPE](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/ddl/graph-type/create/)。 ## 工作原理 `SAMPLE`子句必须指定为完整边模式的边模式填充器的组件;且如果边模式填充器中同时指定了 [WHERE 子句](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/dql/clauses/where/),则`SAMPLE`子句必须写在`WHERE`子句之前。采样会在`WHERE`子句中的过滤条件应用之前执行。关于边模式填充器中各组件出现顺序的更多信息,请参见[完整边模式](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/patterns/edge-patterns/#_2)。 采样对象为包含`SAMPLE`子句的完整边模式所匹配到的边。 所谓向右采样,也即对锚定点右侧的边进行采样,锚定点即为遍历的起始点。例如,在边模式`(v1)<-[e SAMPLE RIGHT]->{1,2}(v2)`中,`v1`即为锚定点。 采样行为由采样上下文决定,后者由以下四个部分组成: - 锚定点 - 连接锚定点的边的边类型 - 连接锚定点的边的方向 - 边模式的每一跳 在遍历过程中,不同的采样上下文相互独立。针对每个采样上下文,会根据指定的采样方法和采样大小对边进行采样。 ## 语法 语法图源码 sample_clause sampling_method sample_size ```` sample_clause ::= 'SAMPLE' 'RIGHT'? sampling_method? sample_size sampling_method ::= 'FIRST_FETCH' | 'RANDOM' | 'UNIQUE_NEIGHBOR' | 'UNQ_NBR' sample_size ::= unsigned_integer '%'? ```` ## 参数 ### `RIGHT` 指定采样时遍历方向的可选关键字。当前仅支持向右采样。 若未指定该关键字,默认为向右采样。 ### `sampling_method` 对于每个采样上下文,选用的采样方法。有效值包括: - `FIRST_FETCH`:采样前 N 条边。此为默认值。 - `RANDOM`:随机采样边。 - `UNIQUE_NEIGHBOR`或`UNQ_NBR`:随机采样连接唯一邻点的边。连接同一对点的平行边会去重后再进行采样。 ### `sample_size` 对于每个采样上下文,采样的大小。支持以下两种指定格式: - 一个无符号整数,代表最大采样数。此时,该无符号整数必须为正整数。 - 一个后跟百分号(`%`)的无符号整数,代表采样百分比。此时,该无符号整数必须在`[0, 100]`范围内。若计算结果为小数,则向上取整。 ## 示例 ### 采样前 2 条边 ```` ''' USE movie MATCH (v1{id: 18})<-[e SAMPLE RIGHT FIRST_FETCH 2 ]-(v2) RETURN labels(v1) AS anchor_labels, v1.id AS anchor_business_id, type(e) AS edge_type, count(*) AS sampled_count ''' ```` 返回: ```` +---------------+--------------------+-----------+---------------+ | anchor_labels | anchor_business_id | edge_type | sampled_count | +---------------+--------------------+-----------+---------------+ | [Genre] | 18 | WithGenre | 2 | | [Movie] | 18 | Direct | 1 | | [Movie] | 18 | Act | 2 | +---------------+--------------------+-----------+---------------+ ```` 上述返回显示存在 3 个采样上下文,具体如下: 1. 对于标签为`Movie`且业务属性`id`为`18`的锚定点,采样了两条边类型为`Act`的边。 2. 对于标签为`Movie`且业务属性`id`为`18`的锚定点,采样了一条边类型为`Direct`的边。原因是数据集中仅存在一条此类边。 3. 对于标签为`Genre`且业务属性`id`为`18`的锚定点,采样了两条边类型为`WithGenre`的边。 ### 随机采样 10% 的边 ```` ''' USE movie MATCH (v1{id: 18})<-[e SAMPLE RIGHT RANDOM 10% ]->(v2) RETURN labels(v1) AS anchor_labels, v1.id AS anchor_business_id, type(e) AS edge_type, count(*) AS sampled_count ''' ```` 返回: ```` +---------------+--------------------+-----------+---------------+ | anchor_labels | anchor_business_id | edge_type | sampled_count | +---------------+--------------------+-----------+---------------+ | [Movie] | 18 | WithGenre | 2 | | [Genre] | 18 | WithGenre | 3 | | [Person] | 18 | Watch | 3 | | [Movie] | 18 | Direct | 1 | | [Movie] | 18 | Act | 5 | +---------------+--------------------+-----------+---------------+ ```` 上述返回显示存在 5 个采样上下文,具体如下: 1. 对于标签为`Movie`且业务属性`id`为`18`的锚定点,采样了五条边类型为`Act`的边。实际存在 44 条此类边,44 的 10% 向上取整即为 5。 2. 对于标签为`Movie`且业务属性`id`为`18`的锚定点,采样了一条边类型为`Direct`的边。 3. 对于标签为`Movie`且业务属性`id`为`18`的锚定点,采样了两条边类型为`WithGenre`的边。 4. 对于标签为`Person`且业务属性`id`为`18`的锚定点,采样了三条边类型为`Watch`的边。 5. 对于标签为`Genre`且业务属性`id`为`18`的锚定点,采样了三条边类型为`WithGenre`的边。 ### 随机采样 2 条连接唯一邻点的边 ```` ''' USE movie MATCH p = (v1@Genre{id: 18})<-[e SAMPLE RIGHT UNIQUE_NEIGHBOR 2]-{1,2}(v2) RETURN length(p) AS hops, transform(nodes(p), n -> n.id) AS node_business_ids, transform(e, edge -> type(edge)) AS edge_types ''' ```` 返回示例: ```` +------+-------------------+--------------------+ | hops | node_business_ids | edge_types | +------+-------------------+--------------------+ | 1 | [18,346] | [WithGenre] | | 1 | [18,601] | [WithGenre] | | 2 | [18,346,20831] | [WithGenre,Act] | | 2 | [18,601,330] | [WithGenre,Watch] | | 2 | [18,346,5026] | [WithGenre,Direct] | | 2 | [18,601,23764] | [WithGenre,Act] | | 2 | [18,346,339] | [WithGenre,Watch] | | 2 | [18,346,7457] | [WithGenre,Act] | | 2 | [18,346,603] | [WithGenre,Watch] | | 2 | [18,601,488] | [WithGenre,Direct] | | 2 | [18,601,9981] | [WithGenre,Act] | | 2 | [18,601,580] | [WithGenre,Watch] | +------+-------------------+--------------------+ ```` 上述返回显示存在 7 个采样上下文,具体如下: 1. 从业务属性`id`为`18`的`Genre`锚定点出发,第一跳采样了两条`WithGenre`边,分别连接业务属性`id`为`346`和`601`的两个`Movie`点。 2. 从业务属性`id`为`346`的`Movie`点继续遍历第二跳: 1. 采样了两条边类型为`Act`的边,分别连接了两个唯一邻点。 2. 采样了一条边类型为`Direct`的边。 3. 采样了两条边类型为`Watch`的边,分别连接了两个唯一邻点。 3. 从业务属性`id`为`601`的`Movie`点继续遍历第二跳: 1. 采样了两条边类型为`Act`的边,分别连接了两个唯一邻点。 2. 采样了一条边类型为`Direct`的边。 3. 采样了两条边类型为`Watch`的边,分别连接了两个唯一邻点。 采样大小`2`会分别应用于每个采样上下文,而不是限制整个查询只返回两条边。由于示例数据集中不存在平行边,因此采样结果中的边均连接唯一邻点。随机采样的具体结果可能因每次执行而不同。