Как использовать Create Unique с Cypher

Моя цель - создать узел + установить для него новое свойство, если оно не существует

если он существует, я просто хочу обновить его свойство

Пробовал это:

MATCH (user:C9 {userId:'44'})
CREATE UNIQUE (user{timestamp:'1111'})
RETURN user

* в случае, если узел со свойством userId = 44 уже существует, я просто хочу установить его свойство в 1111, иначе просто создайте его и установите.

ошибка, которую я получаю:

user already declared (line 2, column 16 (offset: 46))
"CREATE UNIQUE (user{timestamp:'1111'})"

я должен переключиться на слияние или?

Спасибо.


person rayman    schedule 13.11.2015    source источник


Ответы (1)


Да, вы должны использовать оператор MERGE.

MERGE (user:C9 {userId:'44'})
// you can set some initial properties when the node is created if required
//ON CREATE SET user.propertykey = 'propertyvalue' 
ON MATCH SET user.timestamp = '1111'
RETURN user

Вы упоминаете уникальные ограничения - я предполагаю, что у вас есть одна настройка. Вы обязательно должны это сделать, чтобы предотвратить создание дубликатов узлов. Он также создаст индекс схемы для повышения производительности поиска узлов. Если у вас еще нет уникального ограничения, его можно создать так

CREATE CONSTRAINT ON (u:C9) ASSERT u.userId IS UNIQUE

См. документацию Neo4j MERGE.

Наконец, чтобы понять, что происходит в вашем запросе, давайте быстро рассмотрим его построчно.

MATCH (user:C9 { userId:'44' })

Это соответствует узлу с меткой :C9, у которого есть свойство userId со значением 44, и присваивает ему идентификатор user.

CREATE UNIQUE (user{timestamp:'1111'})

Эта строка просто пытается создать новый узел без метки и свойства timestamp со значением '1111'. Исключение, которое вы видите, является результатом использования того же идентификатора user, который уже использовался в первой строке. Однако это не поддерживаемый способ использования CREATE UNIQUE, так как сначала требуется совпадение, а затем создаются биты несуществующего шаблона. Преимущество этого в том, что он останавливает создание этого нежелательного узла (user{timestamp:'1111'}) в графе.

RETURN user

Эта линия довольно понятна и не достигается.

EDIT Кажется, есть некоторая путаница в отношении CREATE UNIQUE и того, когда его следует использовать. Этот запрос

CREATE UNIQUE (user:C9 {timestamp:'1111'})

потерпит неудачу с сообщением

Этот шаблон не поддерживается для CREATE UNIQUE.

Чтобы использовать CREATE UNIQUE, вы должны сначала сопоставить существующий узел, а затем использовать его для создания уникального шаблона в графе. Таким образом, чтобы создать отношение от user ко второму узлу, вы должны использовать

MATCH (user:C9 { userId: '44' }
CREATE UNIQUE (user)-[r:FOO]-(bar)
RETURN r

Если нет отношений типа FOO из user, то будет создан новый узел для представления bar, а между ними будет создана связь типа :FOO. И наоборот, если оператор MATCH не соответствует, то никакие узлы или отношения не будут созданы.

person ceej    schedule 13.11.2015
comment
Спасибо за ваш ответ. но почему вы используете MERGE вместо создания уникального, определяющего это точное требование? - person rayman; 13.11.2015
comment
Вы сказали, что если узел уже существует, вы просто хотите установить свойство. CREATE UNIQUE всегда будет пытаться создать узел, если нет точного совпадения. MERGE либо создаст узел, либо сопоставит существующий. Затем вы можете выполнять различные действия в зависимости от того, создает оператор или соответствует. - person ceej; 13.11.2015
comment
@rayman Я отредактировал свой ответ, чтобы сделать его более ясным. Это помогает? Вы определенно должны использовать MERGE, чтобы удовлетворить ваши требования. - person ceej; 13.11.2015