Оптимизировать Cypher Query для рекомендации фильмов для большого набора данных - PullRequest
0 голосов
/ 30 октября 2018

В настоящее время я работаю над рекомендацией фильма, используя 20-метровый набор данных MovieLens после прочтения https://markorodriguez.com/2011/09/22/a-graph-based-movie-recommender-engine/. Node Movie подключается к жанру с отношением hasGenre, Node Movie подключается к пользователю с отношением hasRating. Я пытаюсь получить всех фильмов с наиболее высоким рейтингом (со рейтингом> 3,0) с помощью запроса (например, История игрушек), который разделяет все жанры с История игрушек . Вот мой запрос Cypher:

MATCH (inputMovie:Movie {movieId: 1})-[r:hasGenre]-(h:Genre)
WITH inputMovie, COLLECT (h) as inputGenres
MATCH (inputMovie)<-[r:hasRating]-(User)-[o:hasRating]->(movie)-[:hasGenre]->(genre) 
WITH  inputGenres,  r, o, movie, COLLECT(genre) AS genres 
WHERE ALL(h in inputGenres where h in genres) and (r.rating>3 and o.rating>3)  
RETURN movie.title,movie.movieId, count(*) 
ORDER BY count(*) DESC

Однако, похоже, моя система не может справиться с этим (используя 16 ГБ ОЗУ, Core i7 4-го поколения и SSD). Когда я выполняю запрос, он достигает 97% ОЗУ, затем Neo4j неожиданно завершает работу (возможно, из-за размера кучи или из-за размера ОЗУ).

  1. Я правильно сделал запрос? Я новичок в Neo4j, так что, вероятно, я делаю запрос неправильно.
  2. Подскажите, пожалуйста, как оптимизировать такой запрос?
  3. Как я могу оптимизировать Neo4j, чтобы он мог обрабатывать большой набор данных со спецификацией моей системы в соответствии с запросом?

Заранее спасибо.

1 Ответ

0 голосов
/ 30 октября 2018

Во-первых, ваш Cypher можно упростить для более эффективного планирования, сопоставляя только то, что нам нужно, и обрабатывая все остальное в WHERE (так что фильтрация может выполняться при сопоставлении)

MATCH (inputMovie:Movie {movieId: 1})-[r:hasGenre]->(h:Genre)
WITH inputMovie, COLLECT (h) as inputGenres
MATCH (inputMovie)<-[r:hasRating]-(User)-[o:hasRating]->(movie)
WHERE (r.rating>3 and o.rating>3) AND ALL(genre in inputGenres WHERE (movie)-[:hasGenre]->(genre))
RETURN movie.title,movie.movieId, count(*) 
ORDER BY count(*) DESC

Теперь, если вы не возражаете добавить данные в график, чтобы найти нужные вам данные, вы можете также разделить запрос на крошечные биты и «кэшировать» результат. Так например

// Cypher 1
MATCH (inputMovie:Movie {movieId: 1})-[r:hasGenre]->(h:Genre)
WITH inputMovie, COLLECT (h) as inputGenres
MATCH (movie:Movie)
WHERE ALL(genre in inputGenres WHERE (movie)-[:hasGenre]->(genre))
// Merge so that multiple runs don't create extra copies
MERGE (inputMovie)-[:isLike]->(movie)

// Cypher 2
MATCH (movie:Movie)<-[r:hasRating]-(user)
WHERE r.rating>3
// Merge so that multiple runs don't create extra copies
MERGE (user)-[:reallyLikes]->(movie)

// Cypher 3
MATCH (inputMovie:Movie{movieId: 1})<-[:reallyLikes]-(user)-[:reallyLikes]->(movie:Movie)<-[:isLike]-(inputMovie)
RETURN movie.title,movie.movieId, count(*) 
ORDER BY count(*) DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...