2017-02-04 8 views
2

Мой последний вопрос был закрыт для дублирования Confused about MERGE sometimes creating duplicate relationship, однако мне не удалось найти решение, и это касается дублированных отношений, а не дубликатов узлов.Почему MERGE иногда создает дубликаты отношений?

У меня есть запрос, когда пользователь VISITED профиль другого пользователя

MATCH (you:User {user_id: { myId }}), (youVisited:User {user_id: { id }}) 
    MERGE (you)-[yvr:VISITED]->(youVisited) 
    SET yvr.seen = false, yvr.created_at = timestamp() 
    RETURN yvr.created_at as visited_at 

я заметил, что в редких случаях, дубликат [:VISITED] отношения происходит. Для (1057)-[:VISITED]->(630), оба имеют то же свойство, и там действительно только должны быть один [:VISITED] независимо от того, что (в следующий раз, когда пользователь посещает, он должен просто MERGE в [:VISITED] и обновлять [:VISITED {created_at: ..., seen: false}] между теми же пользователями узлами:

{ 
    created_at: 1485800172734, 
    seen: false 
} 

enter image description here

Я думал, что точка MERGE, чтобы предотвратить это? Очевидно, что нет, так почему это происходит и как я могу гарантировать этого не происходит?

Я посмотрел некоторые другие т но я не уверен, является ли информация надежной или актуальной. Например: http://neo4j.com/docs/developer-manual/current/cypher/clauses/create-unique/, я должен использовать CREATE UNIQUE вместо этого? Я думал, что MERGE был в значительной степени лучшей заменой для него.

+0

Какая версия Neo4j вы используете, между прочим? Возникла проблема с [неправильной блокировкой MERGE] (https://github.com/neo4j/neo4j/pull/8629), зафиксированной в ветке 3.0, я пытаюсь проверить, попало ли это исправление в текущие выпуски, или если он все еще находится в стадии разработки. – InverseFalcon

+0

Если он еще не исправлен в текущих ветвях, вам может потребоваться вручную заблокировать соответствующие узлы, прежде чем вы выполните MERGE. [Процедуры блокировки APOC] (https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_locking) могут помочь вам здесь. – InverseFalcon

+0

Подтверждено от 2/10/2017, это исправление еще не является частью текущих выпусков. – InverseFalcon

ответ

2

Я согласен, что в некоторых случаях MERGE и CREATE UNIQUE могут использоваться для этой же цели. MERGE не заменяет CREATE UNIQUE, однако.

Например, MERGE допускает несколько совпадений, и его рисунок должен соответствовать полностью соответствует этот граф считается совпадением - он будет просто дублировать частичные совпадения; CREATE UNIQUE, с другой стороны, будет ошибкой в ​​нескольких совпадениях и допускает частичные совпадения - он попытается повторно использовать существующие части вашего графика и добавить недостающие части.

Как уже упоминалось в docs, там также, кажется, разница в отношении уникальности отношений, то есть то, что вы испытываете:

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

Я оставлю его разработчикам Neo4j, чтобы точно объяснить, что это за гарантии. Я могу только сказать, что в вашем конкретном случае CREATE UNIQUE выглядит лучше, чем MERGE в любом случае: если вы намерены разрешать только одно сообщение VISITED от одного пользователя до другого - его последнее посещают - и несколько VISITED отношения являются нарушением вашей модели данных, тогда, во что бы то ни стало, используйте CREATE UNIQUE, чтобы документировать это намерение и одновременно применять его на уровне базы данных.

В этом случае можно утверждать, что отношение VISITED также не имеет особого имени, поскольку оно означает, что может быть больше: один для каждого пользователя, посетившего профиль другого пользователя.

+0

Не могли бы вы показать некоторые примерные запросы, где значительная разница между 'MERGE' и' CREATE UNIQUE' значительна? Я до сих пор не получаю это на 100%. Я использовал «MERGE» повсюду без проблем, без дублирования, пока это не произошло. Все это время я думал, что «MERGE» попытается повторно использовать существующие части вашего графика и добавить недостающие части ». Разве это не то, что он делает, когда вы делаете «MERGE => ON MATCH SET»? Кроме того, как новичок, я не знаком с хорошими соглашениями об именах. Что вы использовали бы вместо «ПОСЕТИТЕ»? 'LAST_VISITED'? – kayla

0

Как упоминалось в моих комментариях, был locking bug с MERGE при переходе Neo4j на планировщик COST.

Насколько я могу сказать, что это работает так:

Из-за ошибки, перепроверил замок не происходит, поэтому после MERGE определяет отношения не существует, он запирает на узлах подготовка к СОЗДАНИЮ отношения, но есть условие гонки между временем проверки существования отношения и блокировкой, поэтому одновременный MERGE или CREATE мог бы создать отношения непосредственно перед приобретением блокировок, в результате чего создаются дублирующие отношения ,

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

Это исправление пока еще не сделано в выпусках Neo4j по состоянию на 2/10/2017.

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

Вы можете сделать это, установив/удалив несуществующие значения на рассматриваемых узлах или используйте APOC locking procedures.