Слияние в Neo4j, когда уникальность основана как на свойстве узла, так и на наличии связи - PullRequest
1 голос
/ 19 июня 2019

В моей модели у меня есть 2 типа узлов;Системы и наборы данных.Каждый набор данных принадлежит к Системе.Это представлено отношением CONTAINS_DATASET.

enter image description here

Как правило;имя набора данных должно быть уникальным в данной системе.Я допускаю дублирование имен наборов данных, если наборы данных содержатся в разных системах.

enter image description here

Я пытаюсь применить это через Cypher так, чтобы;когда кто-то пытается создать набор данных, который является CONTAINED_IN системой;Cypher создаст новый набор данных только в том случае, если имя набора данных не соответствует существующему набору данных, который содержит CONTAINED_IN в этой системе.Система была указана, но я не знаю, как это сделать.Я включил код, который я использую ниже, но это только слияние, в котором не учитывается, в какой системе находится набор данных.

:params
  "data": {
    "System": [
      {
        "name": "System 1",
        "datasets": [
          {
            "name": "Customers"
          }
        ]
      },
      {
        "name": "System 2",
        "datasets": [
          {
            "name": "Customers"
          }
        ]
      },
      {
        "name": "System 3",
        "datasets": [
          {
            "name": "Products"
          }
        ]
      }
    ]
  }

UNWIND {data} as data
UNWIND data.System as systems
UNWIND systems.datasets as datasets
MERGE (sy:System { name: systems.name})
    ON CREATE SET sy.status='New'
    ON MATCH SET  sy.status='Updated'
MERGE (da:Dataset { name: datasets.name})
MERGE (sy)-[:CONTAINS_DATASET]->(dan:Dataset { name: datasets.name })
return *

Приведенный выше запрос также создает 2 дополнительных узла, которыеЯ не ожидаю, поэтому любая помощь с этим будет также оценена:

enter image description here

1 Ответ

2 голосов
/ 19 июня 2019

Вы здесь очень близки, у вашего Cypher есть решение, которое вам нужно:

MERGE (sy)-[:CONTAINS_DATASET]->(dan:Dataset { name: datasets.name })

Этот шаблон имеет связанную (ранее сопоставленную с элементом графика) переменную sy и несвязанную (ранее не сопоставленную ни с чем, первое вхождение в запросе) переменную dan.

MERGE похож на выполнение МАТЧИ паттерна, и тогда поведение будет меняться в зависимости от того, существует ли этот паттерн на графике или нет.

Если он существует в графе (sy имеет отношение: CONTAINS_DATASET к узлу: Dataset с заданным именем), он будет повторно использовать существующие структуры графа, и dan будет привязан к этому существующему подключенному узлу.

Если он не существует в графе, будет создан весь шаблон, и это будет включать создание любых не связанных ранее узлов, например, dan. Если шаблон не существует, он заблокирует связанные части шаблона (sy), дважды проверит, чтобы убедиться, что ничего не изменилось между временем, когда он проверил, и временем, которое потребовалось, и затем это создаст части шаблона, которые ранее не были связаны. sy был ранее связан, поэтому он будет использовать этот же узел вместо создания нового. (dan:Dataset { name: datasets.name }) ранее не был связан, поэтому новый узел с этой меткой и этим свойством будет создан и подключен к sy через отношение: CONTAINS_DATASET.

Таким образом, это поведение должно быть именно тем, что вам нужно: повторно использовать подключенный узел с таким именем, если он существует, или создать новый узел с этим именем и подключить его к sy узлу.

Что касается дубликатов, которые вы видите, то это из-за строки перед ней:

MERGE (da:Dataset { name: datasets.name})

Здесь это не нужно, вы уже удовлетворяете свои потребности с помощью строки после нее, поэтому удалите ее, и ваш запрос должен работать на вас.

Подробнее о поведении MERGE в нашей статье базы знаний .

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