|
|
@@ -0,0 +1,212 @@
|
|
|
+-- ============================================================================
|
|
|
+-- create relation 回归(Cypher: create (a)-[:rel]->(b))
|
|
|
+--
|
|
|
+-- 覆盖 CreateEdges 的聚合实现:
|
|
|
+-- 1) 按 subject 聚合,同一 subject 的所有 relation 合并为一次写;
|
|
|
+-- 2) 每个 distinct object 只做一次存在性检查,缺失对象只补插一次;
|
|
|
+-- 3) 每个 distinct subject 只做一次存在性检查:存在则一次 PushData(C_Merges 含全部
|
|
|
+-- relation),不存在则按带 relation 的方式 insertEntity;
|
|
|
+-- 4) relation_stats 按 (inclass, relation, outclass) 三元组去重。
|
|
|
+--
|
|
|
+-- 存在性检查统一走 omsearch.GetByID(内部经 onesearchproc 按 class 的 core 策略分派)。
|
|
|
+-- 注意:该检查不只是"判断存在",它同时会触发 memdb/localdb 后端对该 class 的数据加载;
|
|
|
+-- 对 core=memory/local 的类,写入必须先于加载完成之后进行,否则先写入的数据会被随后
|
|
|
+-- 的类数据加载覆盖(参见 basic/17cypher/41memdb.mql)。
|
|
|
+--
|
|
|
+-- 四种组合:
|
|
|
+-- 用例1 subject 存在 + object 存在 → 直接 PushData
|
|
|
+-- 用例2 subject 存在 + object 不存在 → 先补插 object,再 PushData
|
|
|
+-- 用例3 subject 不存在 + object 存在 → insertEntity 创建 subject(带 relation)
|
|
|
+-- 用例4 subject 不存在 + object 不存在 → 补插 object + 创建 subject
|
|
|
+-- ============================================================================
|
|
|
+
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 1. 环境准备(可反复执行)
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 先清数据,否则 drop class 会因 "Class ... has data" 失败
|
|
|
+delete from /m3graph_crel/node with version
|
|
|
+/**
|
|
|
+onerror(continue,`not exist`,`not find`,`not found`,`no such`)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+drop edge type m3graph_crel.connect
|
|
|
+/**
|
|
|
+onerror(continue,`not exist`,`not find`,`not found`,`no such`)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+drop class if exists /m3graph_crel/node
|
|
|
+/**
|
|
|
+onerror(continue,`not exist`,`not find`,`not found`,`no such`)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+drop class if exists /m3graph_crel
|
|
|
+/**
|
|
|
+onerror(continue,`not exist`,`not find`,`not found`,`no such`)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+/**
|
|
|
+sleep(1s)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+create class if not exists /m3graph_crel() with core=local, ttl=1 day, namespace='m3graph_crel'
|
|
|
+;
|
|
|
+
|
|
|
+create class if not exists /m3graph_crel/node() with core=local, ttl=1 day, autosearch=true, version=true, nickname='crelnode'
|
|
|
+;
|
|
|
+
|
|
|
+create edge type if not exists m3graph_crel.connect '连接'
|
|
|
+;
|
|
|
+
|
|
|
+/**
|
|
|
+sleep(2s)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 2. 准备已存在的实体
|
|
|
+-- s1/o1 → 用例1;s2 → 用例2;o3 → 用例3
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+insert into /m3graph_crel/node id="crelnode:s1"
|
|
|
+;
|
|
|
+
|
|
|
+insert into /m3graph_crel/node id="crelnode:o1"
|
|
|
+;
|
|
|
+
|
|
|
+insert into /m3graph_crel/node id="crelnode:s2"
|
|
|
+;
|
|
|
+
|
|
|
+insert into /m3graph_crel/node id="crelnode:o3"
|
|
|
+;
|
|
|
+
|
|
|
+/**
|
|
|
+sleep(1s)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 3. 四条 create relation,覆盖 subject/object 存在性的四种组合
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 用例1:subject 存在 + object 存在
|
|
|
+create ('crelnode:s1')-[:connect]->('crelnode:o1')
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例2:subject 存在 + object 不存在
|
|
|
+create ('crelnode:s2')-[:connect]->('crelnode:o2')
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例3:subject 不存在 + object 存在
|
|
|
+create ('crelnode:s3')-[:connect]->('crelnode:o3')
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例4:subject 不存在 + object 不存在
|
|
|
+create ('crelnode:s4')-[:connect]->('crelnode:o4')
|
|
|
+;
|
|
|
+
|
|
|
+/**
|
|
|
+sleep(2s)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 4. 校验
|
|
|
+-- ---------------------------------------------------------------------------
|
|
|
+-- 用例1:边建立,两端实体都在
|
|
|
+match ('crelnode:s1')-[:connect]->('crelnode:o1')
|
|
|
+/**
|
|
|
+output()
|
|
|
+match("graph.edges.len",1,"graph.nodes.len",2)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例1:subject 的 connect 记录了 object
|
|
|
+select connect from /m3graph_crel/node
|
|
|
+/**
|
|
|
+output()
|
|
|
+matchcount("connect",{"_all":["crelnode:o1"]},1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例2:object 被按需补插(CreateEdges 对目标对象做存在性检查并补建)
|
|
|
+select id from /m3graph_crel/node where id='crelnode:o2'
|
|
|
+/**
|
|
|
+output()
|
|
|
+count(1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例2:subject 的 connect 记录了 object
|
|
|
+select connect from /m3graph_crel/node
|
|
|
+/**
|
|
|
+output()
|
|
|
+matchcount("connect",{"_all":["crelnode:o2"]},1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例3:subject 被自动创建
|
|
|
+select id from /m3graph_crel/node where id='crelnode:s3'
|
|
|
+/**
|
|
|
+output()
|
|
|
+count(1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例3:边建立
|
|
|
+match ('crelnode:s3')-[:connect]->('crelnode:o3')
|
|
|
+/**
|
|
|
+output()
|
|
|
+match("graph.edges.len",1,"graph.nodes.len",2)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例3:subject 的 connect 记录了 object
|
|
|
+select connect from /m3graph_crel/node
|
|
|
+/**
|
|
|
+output()
|
|
|
+matchcount("connect",{"_all":["crelnode:o3"]},1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例4:subject 被自动创建
|
|
|
+select id from /m3graph_crel/node where id='crelnode:s4'
|
|
|
+/**
|
|
|
+output()
|
|
|
+count(1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例4:object 被自动补插
|
|
|
+select id from /m3graph_crel/node where id='crelnode:o4'
|
|
|
+/**
|
|
|
+output()
|
|
|
+count(1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例4:边建立
|
|
|
+match ('crelnode:s4')-[:connect]->('crelnode:o4')
|
|
|
+/**
|
|
|
+output()
|
|
|
+match("graph.edges.len",1,"graph.nodes.len",2)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 用例4:subject 的 connect 记录了 object
|
|
|
+select connect from /m3graph_crel/node
|
|
|
+/**
|
|
|
+output()
|
|
|
+matchcount("connect",{"_all":["crelnode:o4"]},1)
|
|
|
+**/
|
|
|
+;
|
|
|
+
|
|
|
+-- 四种用例结束后,node 类里应有 8 条记录:s1,o1,s2,o2,s3,o3,s4,o4
|
|
|
+select id from /m3graph_crel/node
|
|
|
+/**
|
|
|
+output()
|
|
|
+count(8)
|
|
|
+**/
|
|
|
+;
|