Создавайте узлы, если необязательное совпадение возвращает значение null

#database #neo4j #cypher #graph-databases

Вопрос:

Все узлы, которые я буду использовать, имеют уникальные ограничения, связанные с ними.

Я попытался создать новые узлы, подобные этому (я думал о СЛИЯНИИ, чтобы он не создавал узел, если он уже существует):

 MERGE (n:url{url_addr:'test.com'})-[:FROM_DEVICE]->(o:device{mode:'iphone'})
 

И узел уже существует, он возвращает эту ошибку:

 Node(21) already exists with label `url` and property `url_addr` = 'test.com'
 

Это было очевидно, так как я не сопоставил их заранее, поэтому я сделал это для того, чтобы просто передать свойства результатов:

 MATCH (n:url{url_addr:'test.com'}), (o:device{mode:'iphone'})
MERGE (n)-[:FROM_DEVICE]->(o)
 

Но в случае, если какая-либо из этих записей не существует, новые узлы создаваться не будут.

Поэтому я подумал об использовании НЕОБЯЗАТЕЛЬНОГО СООТВЕТСТВИЯ, так как оно заменит любое несуществующее значение нулем, но это означает, что оно также заменит переданные мной свойства нулевыми значениями.

 OPTIONAL MATCH (n:url{url_addr:'test.com'}) RETURN n
MERGE n-[:FROM_DEVICE]->(o:device{mode:'iphone'})
 

Он вернул эту ошибку:

 Failed to create relationship `  REL87(d65d30eb-65f5-4460-b166-15996622cf1b)`, node `n` is missing. If you prefer to simply ignore rows where a relationship node is missing, set 'cypher.lenient_create_relationship = true' in neo4j.conf
 

Поэтому я подумал о том, чтобы использовать операторы CASE, чтобы сначала проверить, вернет ли совпадение значение null, а затем создать узел для определения взаимосвязи, но все пошло не так хорошо:

 OPTIONAL MATCH (n:url{url_addr:'test.com'})
WITH n as test
RETURN CASE
    WHEN test IS NULL THEN CREATE (:url{url_addr:'test.com'})
END
 

Это происходит:

 Invalid input '{': expected
  "!="
  "%"
  ")"
  "*"
  " "
  ","
  "-"
  "."
  "/"
  ":"
  "<"
  "<="
  "<>"
  "="
  "=~"
  ">"
  ">="
  "AND"
  "CONTAINS"
  "ENDS"
  "IN"
  "IS"
  "OR"
  "STARTS"
  "XOR"
  "["
  "^" (line 4, column 51 (offset: 135))
"        WHEN CASE IS NULL THEN CREATE (a:cookie_id{url:'test.com'})"
                                                   ^
 

Удаление свойств узла не помогает.

Ответ №1:

MERGE всегда соответствует или создает весь шаблон целиком. Таким образом, вы, возможно, захотите разделить MERGE предложение, чтобы оно соответствовало или создавало каждый узел и связь:

 MERGE (n:url {url_addr:'test.com'}) // match or create url node
MERGE (o:device {mode:'iphone'})    // match or create device node
MERGE (n)-[:FROM_DEVICE]->(o)       // match or create relationship
 

Возможно, вы также захотите взглянуть на выполнение условного шифрования с помощью процедур APOC:
https://neo4j.com/labs/apoc/4.2/cypher-execution/conditionals/