【发布时间】:2018-02-15 09:53:11
【问题描述】:
我正在使用嵌入在 Java 应用程序中的 Neo4j 社区版进行推荐。我制作了一个自定义函数,其中包含比较两个实体(即产品和用户)的复杂逻辑。这两个实体都作为图中的节点出现,并且每个都有超过 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 毫秒才能运行。现在,为了向特定用户推荐最佳产品,我编写了一个密码查询,它遍历所有产品,计算 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
上述密码查询需要 10 多秒,因为它正在遍历所有产品。在这个密码查询之上,我正在使用 graphaware-reco 模块来满足我的推荐需求(使用预计算、过滤、后处理等)。我想过并行化这个,但社区版不支持集群。现在,随着系统中的用户数量与日俱增,我需要考虑一个可扩展的解决方案。
谁能帮我看看如何优化查询。
【问题讨论】:
-
根据您的描述,您似乎正在使用节点属性来计算两个节点之间的相似度。乍一看,我认为这不是正确的方法...也许您应该重新考虑您的模型并尝试使用 Cypher 将繁重的工作委托给 Neo4j 引擎。
-
也许你应该使用节点和关系而不是属性。
-
谢谢@BrunoPeres。我需要重新考虑如何使用关系而不是属性。然而,大多数属性都是实数(例如用户工资),因此不知道如何将这些信息转换为关系。有什么建议吗?
标签: neo4j cypher graphaware