Как правильно переносить значения с помощью предложения WITH - PullRequest
0 голосов
/ 17 января 2019

У меня очень длинный запрос 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 *

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Я разобрался в проблеме. Я не передавал переменные в качестве параметров и возвращал результаты из процедуры в основной поток запросов.

0 голосов
/ 17 января 2019

Я думаю, что большая проблема здесь - небольшая ошибка в использовании условных процедур.

Если вы хотите вернуть что-либо в условных запросах обратно, вам необходимо явно ВЕРНУТЬ это в запросе.

Кроме того, value, который возвращается, является картой, содержащей значения, возвращаемые запросом, а не само значение. Похоже, вы предполагали, что при выполнении MERGE для одной вещи, что единственная переменная была возвращена неявно и что она была доступна через value, но это неверно. Правильное использование будет примерно таким:

CALL apoc.do.when(("" <> ''),
"MERGE (cloudSuite:CloudSuite{name:''}) RETURN cloudSuite",
'', {})
YIELD value
WITH session, user, environment, browser, os, device, city, country, geoLocation, tenant, company, value.cloudSuite as cloudSuite, application

Псевдоним переменной, полученной внутри карты значений, является причиной того, что WITH необходим для этого случая ( value.cloudSuite as cloudSuite ) для всех случаев использования условных процедур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...