wecisecode 13 órája
szülő
commit
2f1a618dd6

+ 212 - 0
odbctest/mql/problem/basic/graph_local/37create_relation.mql

@@ -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)
+**/
+;