复杂的密码查询与数学公式

时间:2012-05-28 13:53:41

标签: neo4j similarity graph-databases cypher

我有一个包含2种节点的图表:person& food。我有一种关系 - Ate具有属性 - count。每次person 一个food时,关系的count属性都会增加。

我的目标是计算两个person节点之间的相似度。我在网上找到了这个算法来计算相似度,我想用它。如何将其转换为Cypher查询?

sim = 0
for k = 1 to n:
  sim = sim + (1 - Math.abs((N1k/H1 - N2k/H2)))(N1k+N2k)/(H1+H2)

其中:

sim =相似性指数
H1 = food 1吃掉的person项目总数 H2 = food 2吃掉的person项总数 n = 公共food个节点的数量 N1k = {n} {1}}项中{n} {1}}项中的'person项已被吃掉的次数food N2k = food 2在'n'常见person项目中吃过“第k个”food个项目的次数

我已准备好骨架,但我不知道如何继续。

food

帮助表示赞赏!

2 个答案:

答案 0 :(得分:5)

我在Neo4j邮件列表上看到了这个问题,但昨天无法回复。

对于Cypher来说,我是新手。但是,我可以帮助您解决Gremlin中的问题。我可以创建一个类似于你的图形并在其上运行Gremlin遍历。

我的图表如下:

gremlin> g.v(1,2,3,4)_().outE('eats').inV.path{it.name}{it.count}{it.name}  
==>[Neo, 5, Meat]
==>[Neo, 1, Cheese]
==>[Neo, 4, Chicken]
==>[Morpheus, 3, Bread]
==>[Morpheus, 3, Cheese]
==>[Morpheus, 2, Chicken]
==>[Trinity, 1, Apple]
==>[Trinity, 2, Bread]
==>[Trinity, 4, Meat]
==>[Trinity, 2, Cheese]
==>[Smith, 3, Apple]
==>[Smith, 4, Ham]
==>[Smith, 5, Pork]
gremlin> 

我编写了一个遍历来为任何一个顶点生成相似性索引,由start表示对剩余ID数组。我的最终遍历如下:

simarray=[];start=3;
[1,2,4].each{
                p1=start;p2=it;
                first=g.v(p1);
                second=g.v(p2);
                sim=0;
                h1=first.out('eats').count().toFloat();
                h2=second.out('eats').count().toFloat();
                first.outE('eats').as('edges')
                .inV.in('eats').has('id',second.id).back('edges')
                .each{
                        n1k = it.count;
                        n2k = it.inV.inE('eats').outV
                                .has('id', second.id).back(2).count.next();
                        sim = sim + (1 - ((n1k/h1)-(n2k/h2)).abs())*(n1k+n2k)/(h1+h2)
                        };
                simarray.add(sim)
            };
simarray

输出:

gremlin> simarray=[];start=3;[1,2,4].each{p1=start;p2=it; first=g.v(p1); second=g.v(p2); sim=0; h1=first.out('eats').count().toFloat(); h2=second.out('eats').count().toFloat(); first.outE('eats').as('edges').inV.in('eats').has('id',second.id).back('edges').each{n1k = it.count; n2k = it.inV.inE('eats').outV.has('id', second.id).back(2).count.next(); sim = sim + (1 - ((n1k/h1)-(n2k/h2)).abs())*(n1k+n2k)/(h1+h2)}; simarray.add(sim)};simarray
==>0.7857142857142856
==>0.7142857142857143
==>0.14285714285714285

以上遍历直接转换为您的公式/计算。它可以针对性能进行优化w.r.t.图遍历。此外,您可能希望通过Gremlin的文档详细了解相关内容。 https://github.com/tinkerpop/gremlin/wiki

除了您已经加入的Neo4j邮件列表之外,您还可以在Gremlin邮件列表上提出您的疑问: https://groups.google.com/group/gremlin-users

答案 1 :(得分:2)

公式不是很好,但是有两篇关于计算相似度的博客文章,你可能会感兴趣 - 你总是可以根据你的公式调整它更精确 -

这个使用Gremlin: http://blog.everymansoftware.com/2012/02/similarity-based-recommendation-engines.html

这使用Cypher:  http://thought-bytes.blogspot.in/2012/02/similarity-based-recommendations-with.html