Я использую версию сообщества Neo4j, встроенную в приложение java, для рекомендации. Я создал специальную функцию, которая содержит сложную логику сравнения двух сущностей, а именно продукта и пользователей. Обе сущности представлены в виде узлов в графе и имеют более 20 свойств каждая для целей сравнения. Например, Я вызываю эту функцию в следующем формате:
match (e:User {user_id:"some-id"}) with e
match (f:Product {product_id:"some-id"}) with e,f
return e,f,findComparisonValue(e,f) as pref_value;
Этот вызов функции в среднем занимает около 4-5 мсек. Теперь, чтобы порекомендовать лучший продукт конкретному пользователю, я написал запрос cypher, который выполняет итерацию по всем продуктам, вычисляет pref_value и ранжирует их. Мой шифровальный запрос выглядит так:
MATCH (source:User) WHERE id(source)={id} with source
MATCH (reco:Product) WHERE reco.is_active='t'
with reco, source, findComparisonValue(source, reco) as score_result
RETURN distinct reco, score_result.score as score, score_result.params as params, score_result.matched_keywords as matched_keywords
order by score desc
Некоторые идеи о структуре графа:
Total Number of nodes: 2 million
Total Number of relationships: 20 million
Total Number of Users: 0.2 million
Total Number of Products: 1.8 million
Вышеупомянутый запрос cypher занимает более 10 секунд, так как он повторяется по всем продуктам. В дополнение к этому шифровальному запросу я использую модуль graphaware-reco для своих рекомендаций (с использованием предварительного вычисления, фильтрации, постобработки и т. Д.). Я думал об этом распараллеливать, но версия сообщества не поддерживает кластеризацию. Теперь, когда количество пользователей в системе увеличивается день ото дня, мне нужно подумать о масштабируемом решении.
Может ли кто-нибудь помочь мне здесь, как оптимизировать запрос.