2016-08-16 6 views
1

В настоящее время я работаю над рекомендацией запросом фильма, который должен вернуть фильмы с самым «воздействием рекомендации», используя следующий запрос: CypherNeo4j высчитывать вопрос производительности запросов с рекомендацией фильма запросом

match (m:Movie) 
with m, size((m)<-[:LIKED]-(:User)-[:LIKED]->(:Movie)) as score 
order by score desc 
limit 10 
return m.title, score 

После прочтения В моей книге было написано, что это будет простой запрос для neo4j, но время выполнения заняло 32737 мс, чего я не ожидал. Есть ли у кого-нибудь опыт работы с этими типами запросов и какие-либо предложения по повышению производительности? Или должен ли этот запрос работать хорошо, и мне нужно выполнить некоторую настройку конфигурации neo4j/java?

Профиль запроса:

enter image description here

Результат:

enter image description here

ответ

1

Возможно, это то, что вы можете предварительно вычислить.

Ваша оценка по количеству просмотров понравилось каждому пользователю. Почему бы не рассчитать и не сохранить количество фильмов, которые понравились каждому пользователю (если пользователь может смотреть фильм только один раз, а не несколько раз)?

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

MATCH (u:User) 
SET u.likedCount = SIZE((u)-[:LIKED]->(:Movie)) 

Вам нужно будет обновить это каждый раз, когда пользователю понравится (или не понравится) другой фильм.

Когда это предварительно заполняются для всех пользователей, ваш скоринг запрос теперь становится:

MATCH (m:Movie) 
WITH m 
MATCH (m)<-[:LIKED]-(u:User) 
WITH m, SUM(u.likedCount) as score 
ORDER BY score desc 
LIMIT 10 
RETURN m.title, score 

EDIT

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

WITH m, SUM(u.likedCount) - count(u) as score 

Если вы хотите сосчитать различные фильмы понравившихся пользователей в вашем выигрыше, то вы не можете заранее рассчитать и должны использовать что-то вроде ответа stdob.

+0

В этом конкретном сценарии предварительный расчет, по-видимому, является способом перехода, поскольку операторы реального времени занимают не менее 30 секунд. Я думаю, что маркетинг вокруг диаграммы neo4j db немного вводит в заблуждение, поскольку (после прочтения книги db графика) я ожидал, что neo4j с легкостью справится с такими запросами в реальном времени. Спасибо за помощь! –

+0

Я думаю, что когда подграф, рассмотренный по запросу, попадает в десятки миллионов, что все замедляется. Существует также разница между выполнением такого рода запросов в каждом фильме в вашем db (из которых около 10 000), а также для получения оценки для одного фильма или даже нескольких, что, вероятно, будет рассматривать подграфы тысяч узлов, а чем миллионы. – InverseFalcon

1

Попробуйте этот запрос:

MATCH (M:Movie)<-[:LIKED]-(:User)-[:LIKED]->(R:Movie) 
WITH M, 
    size(collect(distinct R)) as score 
RETURN M.title as title, 
     score 
ORDER BY score DESC LIMIT 10 

В качестве опции:

MATCH (M:Movie)<-[:LIKED]-(:User)-[:LIKED]->(R:Movie) 
RETURN M.title as title, 
     count(R) as score 
ORDER BY score DESC LIMIT 10 
+0

Это вернуло количество удалений db с 44038477 до 266085, но удвоило время выполнения с 30920 по 62125 –

+0

@JeroenSlor Попробуйте обновленную версию. –

+0

Второе утверждение (опция) заняло 54320, что на 20 секунд медленнее, чем исходное утверждение в моем вопросе. Любые другие предложения? –