1

Я пытаюсь реализовать алгоритм рекомендаций использование Neo4j, который похож на осуществление на этой page.Удвоение результатов рекомендаций в Neo4j

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

  • следовать другой пользователь
  • игра игра
  • жить в стране

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

За исключением последнего, было бы довольно легко реализовать, используя пример страницы выше, как это:

MATCH (origin)-[r1:FOLLOWS|PLAYS|LIVES_IN]-(c)-[r2:FOLLOWS|PLAYS|LIVES_IN]-(candidate) 
WHERE type(r1)=type(r2) AND NOT (source)-[:FOLLOWS]->(candidate) 
RETURN candidate, SUM(ROUND(r2.weight) AS boost 
ORDER BY boost DESC LIMIT 10 

Однако единственно возможный способ сделать все это сразу бы сделать соединение с другим запросом и обработать результат. Что-то вдоль этих линий:

THE_QUERY_ABOVE 

UNION 

MATCH (origin)<-[r:FOLLOWS]-(candidate) 
RETURN candidate, r.weight as boost 

WITH candidate, boost 
RETURN DISTINCT candidate, SUM(boost) 
ORDER BY boost DESC LIMIT 10 

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

Поэтому мой вопрос: это возможно достичь в одном запросе? и как?

И если это так, есть ли возможное решение, в котором мне не нужно указывать вес в отношениях, чтобы избежать необходимости менять все отношения, когда я хочу изменить приоритеты?

Cheers!

ответ

0

[Изменено]

OPTIONAL MATCH (origin)-[r1:FOLLOWS|PLAYS|LIVES_IN]-(c)-[r2:FOLLOWS|PLAYS|LIVES_IN]-(candidate) 
WHERE type(r1)=type(r2) AND NOT (origin)-[:FOLLOWS]->(candidate) 
WITH origin,candidate,(
    CASE 
    WHEN candidate IS NOT NULL THEN [{ candidate: candidate, boost: SUM(ROUND(r2.weight))}] 
    ELSE NULL END) AS res1 
OPTIONAL MATCH (candidate)-[r3:FOLLOWS]->(origin) 
WITH (
    CASE 
    WHEN candidate IS NOT NULL THEN [{ candidate: candidate, boost: SUM(ROUND(r3.weight))}] 
    ELSE NULL END)+ res1 AS res2 
UNWIND res2 AS result 
RETURN result.candidate AS candidate, SUM(result.boost) AS boost 
ORDER BY boost DESC 
LIMIT 10; 

ли эта работа для вас? Если это не поможет, можете ли вы получить share a console с данными примера?

В нем используются 2 OPTIONAL MATCH статьи, которые разделяют те же самые origin и candidate узлов. Каждое предложение OPTIONAL MATCH позаботится об одном из ваших случаев OR, положив результаты для этого случая в картографическую коллекцию (или NULL, если совпадение не получилось). Ближе к концу коллекции (которые содержат карты той же структуры) объединяются и разматываются как отдельные строки. Наконец, строки с теми же значениями candidate имеют свои значения boost, и первые 10 результатов (по значению форсирования) возвращаются.

+0

Hi @cybersam. Спасибо за быстрый ответ. Однако решение, которое вы предоставили, не совсем то, что я ищу. Это только найдет кандидатов, которые последуют за происхождением, и все остальное ...То, что я ищу, является OR, что означает, что я хочу, чтобы любой пользователь, который мог следить за происхождением, чтобы повысить его оценку рекомендации. – mrstif

+0

См. Мой обновленный ответ. – cybersam

+0

Почти там @cybersam ... Но я также хочу вернуть пользователям, что ** только ** следует за происхождением и ничего больше ... То, как вы это делали, возвращает только тех пользователей, если они сопоставляются как кандидаты в первом ' необязательный матч' ... Я попытался изменить второй «кандидат» на «кандидат2», но он возвращает некоторые странные результаты ... Я могу поделиться с вами консолью, если вы предпочитаете ... – mrstif

0

Вы можете использовать опциональный матч

+0

Привет @Mvde. Это также не идеально подходит для этого варианта использования, так как необязательный матч по-прежнему требует другого совпадения. То, что я пытаюсь сделать, это что-то вроде * ДОПОЛНИТЕЛЬНОГО МАТЧА * для КАЖДОГО пути ... но было бы сложно связать оба совпадения вместе. – mrstif

+0

вы могли бы использовать опцию match (origin) match (origin) - [] ->() и так далее, или я ошибаюсь? – Mvde

+0

Это не так просто @Mvde. Задача здесь состоит в объединении результатов различных путей «ДОПОЛНИТЕЛЬНЫЕ МАТЫ», как вы можете видеть в [решении] @cybersam [http://stackoverflow.com/a/33087863/2194665] – mrstif