У меня очень длинный запрос Cypher, где я загружаю записи из файла и пытаюсь создать узлы и отношения. Некоторые значения могут отсутствовать в файле, поэтому создание узлов и ребер должно быть условным.
Я создал различные части запроса и использовал инструкцию WITH, надеясь передать ссылку на узлы последующим операторам, которым они нужны для создания ребер.
// Mandatory Nodes
MERGE (session:Session{sessionId:"_d6648bbf-f747-42e5-a9b0-adb2cb0aea66-F3AC584AA3E2969240F3E9B285F23C03"})
ON CREATE SET session.ipAddress="207.54.58.254"
MERGE (user:User {UserId:"dfd75378-a6df-4101-aeb7-fc2f866a75cc"})
MERGE (environment:Environment{server:"qac-portal.qac.awsdev.acme.com", type:"MT"})
MERGE (browser:Browser{type:"Chrome"})
ON CREATE SET browser.version="70"
MERGE (os:OS{name:"Win10"})
ON CREATE SET os.version="Win10"
MERGE (device:Device{type:"10.0"})
MERGE (city:City{name:"Atlanta"})
MERGE (country:Country{name:"United States", code:"US"})
MERGE (geoLocation:GeoLocation{latitude:"33.8274", longitude:"-84.3244"})
MERGE (tenant:Tenant{TenantId:"TAMTA1AT2_AX1"})
// Edges between mandatory nodes.
MERGE (session)-[:ASSIGNED_TO]->(user)
MERGE (session)-[:STARTED_AT]->(geoLocation)
MERGE (geoLocation)-[:COORDINATES_FOR]->(city)
MERGE (city)-[:LOCATED_IN]->(country)
MERGE (session)-[:CONNECTED_WITH]->(browser)
MERGE (browser)-[:RUNS_ON]->(device)
MERGE (browser)-[:SUPPORTS]->(os)
MERGE (os)-[:OPERATES]->(device)
MERGE (environment)-[:HOSTS]->(tenant)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
// Optional nodes
CALL apoc.do.when(("TAMTA1AT2_AX1" <> ''),
"MERGE (company:Company{name:'TAMTA1AT2_AX1'})",
'', {})
YIELD value AS company
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company
CALL apoc.do.when(("" <> ''),
"MERGE (cloudSuite:CloudSuite{name:''})",
'', {})
YIELD value AS cloudSuite
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite
CALL apoc.do.when(('sample-hr' <> ''),
"MERGE (application:Application{name:'sample-hr'})",
'', {})
YIELD value AS application
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application
CALL apoc.do.when(('lid://acme.sample-hr.ng1' <> ''),
"MERGE (applicationInstance:ApplicationInstance{applicationId:'lid://acme.sample-hr.ng1'})",
'', {})
YIELD value AS applicationInstance
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance
CALL apoc.do.when(('sample-hr_form_Employee_LRCMyGoalsForm' <> ''),
"MERGE (screen:Screen{name:'sample-hr_form_Employee_LRCMyGoalsForm'})",
'', {})
YIELD value AS screen
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen
CALL apoc.do.when(('sample-hr_form_Employee_LRCMyGoalsForm.ng1' <> '' ),
"MERGE (screenInstance:ScreenInstance{screenId:'sample-hr_form_Employee_LRCMyGoalsForm.ng1'})",
'', {})
YIELD value AS screenInstance
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when(((company IS NOT NULL) AND (tenant IS NOT NULL)),
'MERGE (company)-[r:OWNS]->(tenant)', '',{company:company, tenant:tenant}) YIELD value AS owns
// Edges between optional nodes
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant,
company, cloudSuite, applicationInstance, application, screen, screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (screen IS NOT NULL) AND (screenInstance IS NOT NULL)),
'MERGE (screenInstance)-[r:INSTANCE_OF]->(screen)', '',{screen:screen, screenInstance:screenInstance}) YIELD value AS instanceOf
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when(((application IS NOT NULL) AND (applicationInstance IS NOT NULL)) AND ("Accessed" IN ["Accessed", "Launched", "Entered", "Exited"]),
'MERGE (application)-[r:DEPLOYS]->(applicationInstance)', '',{application:application, applicationInstance:applicationInstance}) YIELD value AS deploys
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when(((application IS NOT NULL) AND (cloudSuite IS NOT NULL)) AND ("Accessed" IN ["Accessed", "Launched", "Entered", "Exited"]),
'MERGE (application)-[r:BELONGS_TO]->(cloudSuite)' , '',{application:application, cloudSuite:cloudSuite}) YIELD value AS belongs_to
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when(((application IS NOT NULL) AND (browser IS NOT NULL)) AND ("Accessed" IN ["Accessed", "Launched", "Entered", "Exited"]),
'MERGE (application)-[r:COMPATIBLE_WITH]->(browser)', '',{application:application, browser:browser}) YIELD value AS compatible_with
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (screenInstance IS NOT NULL) AND (applicationInstance IS NOT NULL)),
'MERGE (screenInstance)-[r:VIEWED_ON]->(applicationInstance)', '',{screenInstance:screenInstance, applicationInstance:applicationInstance}) YIELD value AS viewed_on
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (application IS NOT NULL) AND (screen IS NOT NULL)),
'MERGE (application)-[:IMPLEMENTS]->(screen)', '',{application:application, screen:screen}) YIELD value AS implements
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.when(((tenant IS NOT NULL) AND (application IS NOT NULL)),
'MERGE (tenant)-[r:PROVISIONED]->(application)', '',{tenant:tenant, application:application}) YIELD value AS provisioned
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, cloudSuite, application, applicationInstance, screen, screenInstance
CALL apoc.do.case(
[ "Accessed" = "Logged In", "MERGE (session)-[:LOGGED_IN {start='2018-11-06 11:39:10'}]->(applicationInstance)",
"Accessed" = "Logged Out", "MERGE (session)-[:LOGGED_OUT {end='2018-11-06 11:39:10'}]->(tenant)",
"Accessed" = "Time Out", "MERGE (session)-[:TIMED_OUT {timeout='2018-11-06 11:39:10'}]->(tenant)",
"Accessed" = "Accessed", 'MERGE (session)-[:ACCESSED]->(screenInstance)',
"Accessed" = "Launched", 'MERGE (session)-[:LAUNCHED]->(applicationInstance)',
"Accessed" = "Entered", 'MERGE (session)-[:ENTERED]->(applicationInstance)',
"Accessed" = "Exited", 'MERGE (session)-[:EXITED]->(applicationInstance)' ],
'',
{applicationInstance:applicationInstance, screenInstance:screenInstance, session:session, tenant:tenant})
YIELD value AS action
RETURN *
Когда я запускаю запрос в браузере Neo4j, он выполняется и дает мне результат: добавлено 10 меток, создано 10 узлов, установлено 16 свойств, создано 9 отношений, выполнено через 8 мс. Это означает, что не все узлы были созданы. Фактически он завершает первые 2 раздела: Обязательные узлы и ребра и останавливается сразу после создания первого узла: «Компания» в дополнительном разделе «Узлы». Я не имею ни малейшего понятия о том, почему бы остановиться прямо сейчас. Я предполагаю, что я делаю что-то не так с предложением WITH, что вызывает следующий вопрос. Должен ли я использовать эти многие СО?
Заранее благодарю за любую помощь.
Редактировать 1
Спасибо, что исправили проблему с частью Nodes:
CALL apoc.do.when(('xxxForm.ng1' <> '' ),
"MERGE (screenInstance:ScreenInstance{screenId:'ljhgjhn-gjhhkjhkhr_form_Employee_LRCMyGoalsForm.ng1'}) RETURN screenInstance",
'', {})
YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, value.application as application, value.company as company, value.cloudSuite as cloudSuite, value.applicationInstance as applicationInstance, value.screen as screen, value.screenInstance as screenInstance
Я предполагал, что тот же подход использования карты значений будет работать с частью ребер, но я сталкиваюсь с той же проблемой там. Должны ли я значения на карте все еще быть доступными в этой точке?
CALL apoc.do.when(((company IS NOT NULL) AND (tenant IS NOT NULL)),
'MERGE (company)-[r:OWNS]->(tenant) RETURN company, tenant', '',{company:company, tenant:tenant}) YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, value.application as application, value.company as company, value.cloudSuite as cloudSuite, value.applicationInstance as applicationInstance, value.screen as screen, value.screenInstance as screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (screen IS NOT NULL) AND (screenInstance IS NOT NULL)),
'MERGE (screenInstance)-[r:INSTANCE_OF]->(screen) RETURN screenInstance, screen', '',{screen:screen, screenInstance:screenInstance}) YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, value.application as application, value.company as company, value.cloudSuite as cloudSuite, value.applicationInstance as applicationInstance, value.screen as screen, value.screenInstance as screenInstance
Редактировать 2
MERGE (session:Session{sessionId:"_d6648bbf-f747-42e5-a9b0-adb2cb0aea66-F3AC584AA3E2969240F3E9B285F23C03"})
ON CREATE SET session.ipAddress="207.54.58.254"
WITH session
MERGE (user:User {UserId:"dfd75378-a6df-4101-aeb7-fc2f866a75cc"})
WITH session, user
MERGE (environment:Environment{server:"xxx.yyy.zzz.com", type:"MT"})
WITH session, user, environment
MERGE (browser:Browser{type:"Chrome"})
ON CREATE SET browser.version="70"
WITH session, user, environment, browser
MERGE (os:OS{name:"Win10"})
ON CREATE SET os.version="Win10"
WITH session, user, environment, browser, os
MERGE (device:Device{type:"10.0"})
WITH session, user, environment, browser, os, device
MERGE (city:City{name:"Atlanta"})
WITH session, user, environment, browser, os, device, city
MERGE (country:Country{name:"United States", code:"US"})
WITH session, user, environment, browser, os, device, city, country
MERGE (geoLocation:GeoLocation{latitude:"33.8274", longitude:"-84.3244"})
WITH session, user, environment, browser, os, device, city, country, geoLocation
MERGE (tenant:Tenant{TenantId:"TAMTA1AT2_AX1"})
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (session)-[:ASSIGNED_TO]->(user)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (session)-[:STARTED_AT]->(geoLocation)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (geoLocation)-[:COORDINATES_FOR]->(city)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (city)-[:LOCATED_IN]->(country)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (session)-[:CONNECTED_WITH]->(browser)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (browser)-[:RUNS_ON]->(device)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (browser)-[:SUPPORTS]->(os)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (os)-[:OPERATES]->(device)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
MERGE (environment)-[:HOSTS]->(tenant)
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant
// Creating Optional nodes.
CALL apoc.do.when(('sfgsfgn-ghr' <> ''),
"MERGE (application:Application{name:'afasdfn-ghr'}) RETURN application",
'', {})
YIELD value AS mapApplication
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, mapApplication.application as application
CALL apoc.do.when(("TAMTA1AT2_AX1" <> ''),
"MERGE (company:Company{name:'TAMTA1AT2_AX1'}) RETURN company",
'', {})
YIELD value AS mapCompany
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, mapCompany.company as company
CALL apoc.do.when(("" <> ''),
"MERGE (cloudSuite:CloudSuite{name:''}) RETURN cloudSuite",
'', {})
YIELD value AS mapCloudSuite
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, mapCloudSuite.cloudSuite as cloudSuite
CALL apoc.do.when(('lid://afasfafdsghr.ng1' <> ''),
"MERGE (applicationInstance:ApplicationInstance{applicationId:'lid://gfsgsr.ng1'}) RETURN applicationInstance",
'', {})
YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, value.applicationInstance as applicationInstance
CALL apoc.do.when(('lawson-ghr_form_Employee_LRCMyGoalsForm' <> ''),
"MERGE (screen:Screen{name:'lafsafsdfn-ghr_form_Employee_LRCMyGoalsForm'}) RETURN screen",
'', {})
YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, value.screen as screen
CALL apoc.do.when(('sfgfsg-ghr_form_Employee_LRCMyGoalsForm.ng1' <> '' ),
"MERGE (screenInstance:ScreenInstance{screenId:'sgfdn-ghr_form_Employee_LRCMyGoalsForm.ng1'}) RETURN screenInstance",
'', {})
YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, value.screenInstance as screenInstance
// Creating Edges for optional nodes
CALL apoc.do.when(((company IS NOT NULL) AND (tenant IS NOT NULL)),
'WITH company, tenant MERGE (company)-[r:OWNS]->(tenant)', '',{company:company, tenant:tenant}) YIELD value as owns
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (screen IS NOT NULL) AND (screenInstance IS NOT NULL)),
'WITH screen, screenInstance MERGE (screenInstance)-[i:INSTANCE_OF]->(screen)', '',{screenInstance:screenInstance, screen:screen}) YIELD value AS instance_of
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when(((application IS NOT NULL) AND (applicationInstance IS NOT NULL)) AND ("Accessed" IN ["Accessed", "Launched", "Entered", "Exited"]),
'WITH application, applicationInstance MERGE (application)-[d:DEPLOYS]->(applicationInstance)', '',{application:application, applicationInstance:applicationInstance}) YIELD value AS deploys
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when(((application IS NOT NULL) AND (cloudSuite IS NOT NULL)) AND ("Accessed" IN ["Accessed", "Launched", "Entered", "Exited"]),
'WITH application, cloudSuite MERGE (application)-[b:BELONGS_TO]->(cloudSuite)' , '',{application:application, cloudSuite:cloudSuite}) YIELD value AS belongs_to
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when(((application IS NOT NULL) AND (browser IS NOT NULL)) AND ("Accessed" IN ["Accessed", "Launched", "Entered", "Exited"]),
"WITH application, browser MERGE (application)-[c:COMPATIBLE_WITH]->(browser)", '',{application:application, browser:browser}) YIELD value AS compatible_with
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (applicationInstance IS NOT NULL)),
"WITH screenInstance, applicationInstance MERGE (screenInstance)-[v:VIEWED_ON]->(applicationInstance)", '',{screenInstance:screenInstance, applicationInstance:applicationInstance}) YIELD value AS viewed_on
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when((("Accessed" = "Accessed") AND (application IS NOT NULL) ),
"WITH application, screen MERGE (application)-[i:IMPLEMENTS]->(screen)", '',{application:application, screen:screen}) YIELD value AS implements
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.when(((tenant IS NOT NULL) AND (application IS NOT NULL)),
'WITH tenant, application MERGE (tenant)-[r:PROVISIONED]->(application)', '',{tenant:tenant, application:application}) YIELD value AS provisioned
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, application, company, cloudSuite, applicationInstance, screen, screenInstance
CALL apoc.do.case(
[ "Accessed" = "Logged In", "MERGE (session)-[:LOGGED_IN {start='2018-11-06 11:39:10'}]->(applicationInstance)",
"Accessed" = "Logged Out", "MERGE (session)-[:LOGGED_OUT {end='2018-11-06 11:39:10'}]->(tenant)",
"Accessed" = "Time Out", "MERGE (session)-[:TIMED_OUT {timeout='2018-11-06 11:39:10'}]->(tenant)",
"Accessed" = "Accessed", 'MERGE (session)-[:ACCESSED]->(screenInstance)',
"Accessed" = "Launched", 'MERGE (session)-[:LAUNCHED]->(applicationInstance)',
"Accessed" = "Entered", 'MERGE (session)-[:ENTERED]->(applicationInstance)',
"Accessed" = "Exited", 'MERGE (session)-[:EXITED]->(applicationInstance)' ],
'',
{applicationInstance:applicationInstance, session:session, tenant:tenant})
YIELD value
RETURN *