2013-12-16 3 views
1

Я пытаюсь реализовать мягкое удаление в Neo4j. График описан в Cypher с точки зрения Алисы как таковой:Neo4j: реализация мягкого удаления с необязательными отношениями

(clyde:User)<-[:FOLLOWS]-(alice:User)-[:LIKES]->(bob:User) 

Вместо фактически удаления узла и его отношения, я

  1. меняет свою этикетку, так что больше не может рассматриваться непосредственно , то есть сбрасывая метку User и добавляя метку _User (обратите внимание на подчеркивание)
  2. , заменяя ее отношения, так что больше не могут быть достигнуты моими обычными запросами, например удаляя свои отношения :FOLLOWS и заменяя его отношениями :_FOLLOWS.

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

В результате мягкого удаления Алисы должно быть так:

(clyde:User)<-[:_FOLLOWS]-(alice:_User)-[:_LIKES]->(bob:User) 

Моя первая попытка запроса была такова:

match (user:User {Id: 1}) 
optional match (user)-[follows:FOLLOWS]->(subject) 
remove user:User set user:_User 
delete follows 
create (user)-[:_FOLLOWS]->(subject); 

Проблема в том, что, когда этот пользователь не следует никому, запрос пытается создать взаимосвязь между user и null, потому что второе совпадение необязательно, поэтому оно дает мне эту ошибку: Other node is null.

Моя вторая попытка была такова:

match (user:User {Id: 1}) 
remove user:User set user:_User 
optional match (user)-[follows:FOLLOWS]->(subject) 
foreach (f in filter(f in collect({r: follows, n: subject}) where f.r is not null) | delete f.r create (user)-[:_FOLLOWS]->(f.n)); 

Так я кладу отношения и объекта в карте, собирая эти карты в коллекции, бросая все «пустые» карту прочь и перекручивание по коллекции. Но этот запрос дает мне эту ошибку:

SyntaxException: Invalid input '.': expected an identifier character, node labels, a property map, whitespace or ')' (line 1, column 238) 

Кто-нибудь знает, как я могу это исправить?

Спасибо, Jan

ответ

2

Не могли бы вы изменить метку первой, а затем сопоставить для отношений? Тогда вы должны быть в состоянии использовать «без дополнительных» матча, и не приходится иметь дело со случаями, когда нет следующих отношения, что-то вроде

MATCH (user:User {Id: 1}) 
REMOVE user:User SET user:_User 
WITH user 
MATCH (user)-[follows:FOLLOWS]->(subject) 
DELETE follows 
CREATE (user)-[:_FOLLOWS]->(subject) 

Или вы могли бы нести пользователь, следует и с учетом и фильтр где объект не является нулевым.Что-то вроде

MATCH (user:User {Id: 1}) 
OPTIONAL MATCH (user)-[follows:FOLLOWS]->(subject) 
REMOVE user:User SET user:_User 
WITH user, follows, subject 
WHERE subject IS NOT NULL 
DELETE follows 
CREATE (user)-[:_FOLLOWS]->(subject) 

Edit:
Если проблема заключается в том, что вы хотите сделать это для более чем одного вида отношений, то вы можете попробовать

MATCH (user:User {Id: 1}) 
REMOVE user:User SET user:_User 
WITH user 
MATCH (user)-[f:FOLLOWS]->(other) 
DELETE f 
CREATE (user)-[:_FOLLOWS]->(other) 
WITH user LIMIT 1 
MATCH (user)-[l:LIKES]->(other) 
DELETE l 
CREATE user-[:_LIKES]->(other) 

Вы можете сохранить его продления с другие типы отношений, просто обязательно ограничьте user, когда вы переносите, так как несколько совпадений (user)-[r]->(other) означает, что для пользователя имеется несколько результатов для пользователя, или вы будете запускать следующую часть запроса несколько раз.

Я не думаю, что есть общий способ сделать это в шифре, так как вы не можете динамически построить тип отношений (т.е. CREATE (a)-[newRel:"_"+type(oldRel)]->(b) не работает)

ли что-то подобное, что вы ищете или я не понимаю ваш вопрос?

+0

Я думаю, что это работает, если между пользователями существует только один вид отношений, то есть только:: FOLLOWS. Но в моем случае на самом деле больше, например ': LIKES', которые также должны быть заменены. Если у пользователя нет, например, отношений ': FOLLOWS' и хотя бы одного отношения': LIKES', я не думаю, что могу нести пользователя. –

+0

Не уверен, что вы имеете в виду. Ваш вопрос заключался в обработке нулевого случая из необязательного совпадения в вашем запросе («Проблема в том, что ...»), вот что я ответил. – jjaderberg

+0

Конечно, я должен был быть более ясным. Я хочу иметь возможность заменить несколько типов отношений, как необязательных, так и обязательных. Ваше решение не работает, если у пользователя нет отношений: FOLLOWS, потому что он использует точное совпадение, и пользователю не нужно переносить на: часть LIKES, потому что она не соответствует в: части FOLLOWS. Именно поэтому я использовал опциональное совпадение в первую очередь, но это приводит к двум ошибкам в исходном вопросе. –

 Смежные вопросы

  • Нет связанных вопросов^_^