| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- -- ============================================================================
- -- 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)
- **/
- ;
|