
рд╕реНрдкреНрд░рд┐рдВрдЧ рдЗрдВрдЯреАрдЧреНрд░реЗрд╢рди рдлреНрд░реЗрдорд╡рд░реНрдХ JSON рдЧреНрд░рд╛рдл рдХреЗ рд░реВрдк рдореЗрдВ рд╕рднреА EIP рдШрдЯрдХреЛрдВ рдФрд░ рдЙрдирдХреЗ рд░рд┐рд╢реНрддреЛрдВ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рджреЗрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИ ред рдпрд╣ рдЕрдзреНрдпрдпрди рдФрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдлрд╕реЛрд╕, Google рдЯреВрд▓ рдореЗрдВ рд╕реЗ рдПрдХ рдирд╣реАрдВ (рдЬрд┐рдирдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ / рджреЛ рдмрд╛рд░ ) рдЗрд╕ рддрд░рд╣ рдХреЗ рдЧреНрд░рд╛рдл рдХреЛ рджреЗрдЦрдиреЗ рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд▓рдЪреАрд▓рд╛рдкрди рджреЗрддрд╛ рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдпрд╣ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рдПрдХ Neo4j рдЧреНрд░рд╛рдлрд┐рдХрд▓ DBMS рдореЗрдВ рдПрдХ рдЧреНрд░рд╛рдл рдЖрдпрд╛рдд рдХрд░рдХреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдП , рдЬрд╣рд╛рдВ рдЗрд╕ рддрд░рд╣ рдХрд╛ рд▓рдЪреАрд▓рд╛рдкрди рдкрд╣рд▓реЗ рдЖрддрд╛ рд╣реИред
(tl;dr)
, :
- JSON URL.
- Cypher- Neo4j Browser, URL.
, , .
, Spring Neo4j Cypher. , тАУ .
JSON?
2 :
spring-integration-http ( spring-integration-webflux), , Integration Graph Controller.spring-integration-core Spring Boot Actuator, endpoint integrationgraph ( web).
:
{
"contentDescriptor": {
"providerVersion": "5.2.4.RELEASE",
"providerFormatVersion": 1.1,
"provider": "spring-integration",
"name": "analog"
},
"nodes": [
{
"nodeId": 3,
"componentType": "ExecutorSubscribableChannel",
"name": "brokerChannel"
},
],
"links": [
{
"from": 19,
"to": 8,
"type": "output"
},
]
}
3 :
contentDescriptor тАУ ; name ( spring.application.name).nodes тАУ EIP-, . name, componentType nodeId, , .links , .. EIP-. from to nodeId . type , 5: input, output, route, error, discard.
( EIP) !
, , , componentType channel.
Spring Integration.
тАЬтАЭ, тАУ тАЬтАЭ, : nodes links . .
Neo4j, - , , , http://localhost:8080/actuator/integrationgraph ( Spring Boot Actuator). JSON, , .
CORS, . Spring Boot (+Actuator) , :
management:
endpoints:
web:
exposure:
include: '*'
cors:
allowed-origins: '*'
allowed-methods: '*'
( production!)
Spring Integration, . .
Neo4j?
Neo4j, 2 :
Neo4j (, ?)
:
Cypher- APOC
- Neo4j, . Neo4j Sandbox .
Neo4j 4.0.1, , . APOC , 2 Neo4j.
1:
Spring Integration, JSON-, , тАЬ тАЭ : тАУ , тАУ , тАУ . : nodeId, nodeName componentType. org.springframework.integration.graph.IntegrationNode, ( ).
, Neo4j - :
JSON URL, .
Cypher :
// (1) load JSON from URL:
WITH "http://localhost:8080/actuator/integrationgraph" AS url
CALL apoc.load.json(url) YIELD value
WITH value AS json, value.contentDescriptor AS jsonDescriptor
// (2) descriptor:
MERGE (descriptor:Descriptor {name: jsonDescriptor.name})
ON CREATE SET
descriptor.providerVersion = jsonDescriptor.providerVersion,
descriptor.providerFormatVersion = jsonDescriptor.providerFormatVersion,
descriptor.provider = jsonDescriptor.provider
// (3) nodes:
WITH json, descriptor
UNWIND json.nodes AS jsonNode
MERGE (node:Node {nodeId: jsonNode.nodeId})
ON CREATE SET
node.componentType = jsonNode.componentType,
node.name = jsonNode.name
// (4) links:
WITH json, descriptor, node
UNWIND json.links AS jsonLink
MATCH (a:Node {nodeId: jsonLink.from}), (b:Node {nodeId: jsonLink.to})
MERGE (a)-[link:Link {type: jsonLink.type}]->(b)
// (5) result:
RETURN descriptor, node, link
URLNeo4j SandboxтАЩ, , .. localhost . JSON- , ├│.
Cypher, ( ):
- APOC-
apoc.load.json(url) JSON- json, тАУ jsonDescriptor. Descriptor, jsonDescriptor.
MERGE, , . , MERGE CREATE.- JSON- (
nodes) UNWIND Node, name componentType. - (
links), Link MATCH, . - , : , .
Neo4j Browser JSON-, :

-, : EIP- , , Neo4j Browser, , Cypher-:

тАЬтАЭ ( ) , . , .
, :
- , EIP- , , , , ,
serverR... , , , . - ,
Link, type. , Cypher, тАЬ тАЭ . - , , , тАУ , .
, , , тАж
2:
, : , , . Neo4j Browser ( , ), GraSS (Graph Style Sheet), Neo4j BrowserтАЩ. , , :style ( ):

. Neo4j Browser , , ( ) Node. Neo4j Browser, , . тАЬтАЭ EIP-: , , .. , , , Cypher- - тАЬ тАЭ . , Cypher тАЬ тАЭ : тАУ , . APOC. apoc.merge.node, / , :
merge nodes with dynamic labels, with support for setting properties ON CREATE or ON MATCH
: , /, тАУ , . , Cypher- , тАЬтАЭ , , channel. CASE.
: -, , -, JSON- Cypher MERGE, APOC тАУ apoc.merge.relationship:
merge relationship with dynamic type, with support for setting properties ON CREATE or ON MATCH
Neo4j 3.APOC- apoc.merge.(relationship|node) 3.x ( , Neo4j Sandbox 2020) onMatchProps, .
, - тАЬтАЭ , , , , , тАУ , . , , , . , тАЬтАЭ . DESCRIBES - .
, , :
// (1) load JSON from URL:
WITH "http://localhost:8080/actuator/integrationgraph" AS url
CALL apoc.load.json(url) YIELD value
WITH value AS json, value.contentDescriptor AS jsonDesc
// (2) descriptor:
MERGE (descriptor:Descriptor {name: jsonDesc.name})
ON CREATE SET
descriptor.providerVersion = jsonDesc.providerVersion,
descriptor.providerFormatVersion = jsonDesc.providerFormatVersion,
descriptor.provider = jsonDesc.provider,
descriptor.updated = localdatetime()
ON MATCH SET
descriptor.updated = localdatetime()
// (3) nodes:
WITH json, descriptor
UNWIND json.nodes AS jsonNode
CALL apoc.merge.node(
/*labels*/ ['Node',
CASE
WHEN jsonNode.componentType IS NULL THEN "<unknown>"
WHEN toLower(jsonNode.componentType) ENDS WITH "channel" THEN "channel"
WHEN toLower(jsonNode.componentType) ENDS WITH "adapter" THEN "adapter"
WHEN jsonNode.componentType CONTAINS '$' THEN "<other>"
ELSE jsonNode.componentType
END],
/*identProps*/ {nodeId: jsonNode.nodeId, appName: descriptor.name},
/*onCreateProps*/{name: jsonNode.name, componentType: jsonNode.componentType},
/*onMatchProps*/ {}
) YIELD node
MERGE (descriptor)-[:DESCRIBES]->(node)
// (4) links:
WITH json, descriptor, node
UNWIND json.links AS jsonLink
MATCH (a:Node {nodeId: jsonLink.from})<-[:DESCRIBES]-(descriptor)-[:DESCRIBES]->(b:Node {nodeId: jsonLink.to})
CALL apoc.merge.relationship(a, toUpper(jsonLink.type), {}, {}, b, {}) YIELD rel
// (5) result:
RETURN descriptor
URLNeo4j SandboxтАЩ, , .. localhost . JSON- , ├│.
, - 5 ( ):
- JSON ;
- / , ;
/ , Node ( - ), :
<unknown>, (, , , , , UnzipTransformer);channel, channel, , ExecutorSubscribableChannel;adapter, adapter, , inbound-channel-adapter;<other>, $, ( ) , , ServerConfig$$Lambda$994/0x00000008010fd440;- , , ,
"componentType": "gateway".
componentType . DESCRIBES.
- / ,
type JSON- .
. , , nodeId. , appName . - .
, , - . .
Spring Integration, ( 350+ 330+ , . ). Neo4j , , , :

Neo4j , . , Neo4j bin/neo4j-admin, memrec , , .
, GraSS- (, ) Neo4j BrowserтАЩ, :style.
, MATCH (a) RETURN a, - . , , , . ( name):
WITH "analog" AS appName
MATCH (:Descriptor {name: appName})-[:DESCRIBES]->(n:Node)-[l*0..1]-(:Node)
RETURN n, l
, , ( ). , .
:

, . Cypher- (. .4 ), style.grass, componentType Node. , . , GraSS- EIP- :
node.Node {
defaultCaption: "<id>";
caption: "{name}";
}
Neo4j Browser тАУ :

. , , Neo4j Browser, . .
, Neo4j Spring Integration. , , , :
32 27 :

37 41 :

57 54 :

350 332 :

, JSON- EIP- Spring Integration. Neo4j . Cypher тАЬ тАЭ , . . , ( ) Cypher-, .
тАУ Neo4j Browser. , ; , . , тАУ . Cypher , . , //, / , , / / , / .. , .
рдореВрд▓ Cypher рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рд▓реЗрдЦ рдпрд╣рд╛рдБ рд╣реИ ред