【问题标题】:Count relationship pairs in Neo4j在 Neo4j 中计算关系对
【发布时间】:2013-05-09 07:45:47
【问题描述】:

我开始与 Neo4j 打交道,所以我对这个主题并不是很精通。在下图中,我有 2 模式(二分)图,其中绿色节点表示“文档”,红色节点表示出现在特定文档中的“术语”。 (现实世界的图实际上是巨大的:大约 20.000.000 个文档和 25.000 个术语)。

我想知道如何计算 neo4j(在 Cypher 或 Java 中)中的术语共现对。查询的期望输出应该是:

# Example: Pair (term-1, term-2) occurs in doc-1 and in doc-3
# Frequency for pair (term-1, term-2) should be 2
# termA | term B | frequency
term-1 | term-2 | 2
term-1 | term-3 | 1
term-2 | term-3 | 2

图表可在http://console.neo4j.org/r/7fmo7c获取

在 Neo4j 中重现测试图的代码

set name root
mkrel -t ROOT -c -v
cd 1
set name doc-1
set type document
mkrel -t HAVE -cv
cd 2
set name term-1
set type term
cd ..
mkrel -t HAVE -cv
cd 3
set name term-2
set type term
cd ..
mkrel -t HAVE -cv
cd 4
set name term-3
set type term
mkrel -t HAVE -d INCOMING -c
cd 5
set name doc-2
set type document
mkrel -t HAVE -d OUTGOING -n 3
cd 3
mkrel -t HAVE -d INCOMING -c
cd 6
set name doc-3
set type document
mkrel -t HAVE -d OUTGOING -n 2

用 Java 重现测试图的代码

import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;

public class CountPairs {
    private static final String DB_PATH = "test.db";
    private static GraphDatabaseService graphDb;

    public static void main(String[] args) {
        graphDb = new GraphDatabaseFactory().
                newEmbeddedDatabaseBuilder(DB_PATH).
                setConfig(GraphDatabaseSettings.node_keys_indexable, "name, type").
                setConfig(GraphDatabaseSettings.node_auto_indexing, "true").
                newGraphDatabase();

        Transaction tx = graphDb.beginTx();
        Node doc1, doc2, doc3 = null;
        Node term1, term2, term3 = null;
        Relationship rel1, rel2, rel3, rel4, rel5, rel6, rel7 = null;
        try
        {
            // Create nodes
            doc1 = graphDb.createNode();
            doc2 = graphDb.createNode();
            doc3 = graphDb.createNode();
            term1 = graphDb.createNode();
            term2 = graphDb.createNode();
            term3 = graphDb.createNode();
            // Set properties
            doc1.setProperty("name", "doc1");
            doc1.setProperty("type", "document");
            doc2.setProperty("name", "doc2");
            doc2.setProperty("type", "document");
            doc3.setProperty("name", "doc3");
            doc3.setProperty("type", "document");
            // Set properties
            term1.setProperty("name", "term1");
            term1.setProperty("type", "term");
            term2.setProperty("name", "term2");
            term2.setProperty("type", "term");
            term3.setProperty("name", "term3");
            term3.setProperty("type", "term");
            // Create relations
            rel1 = doc1.createRelationshipTo(term1, DynamicRelationshipType.withName("HAVE"));
            rel2 = doc1.createRelationshipTo(term2, DynamicRelationshipType.withName("HAVE"));
            rel3 = doc1.createRelationshipTo(term3, DynamicRelationshipType.withName("HAVE"));
            rel4 = doc2.createRelationshipTo(term2, DynamicRelationshipType.withName("HAVE"));
            rel5 = doc2.createRelationshipTo(term3, DynamicRelationshipType.withName("HAVE"));
            rel6 = doc3.createRelationshipTo(term1, DynamicRelationshipType.withName("HAVE"));
            rel7 = doc3.createRelationshipTo(term2, DynamicRelationshipType.withName("HAVE"));

            tx.success();
        }
        catch(Exception e)
        {
            tx.failure();
        }
        finally
        {
            tx.finish();
        }

        graphDb.shutdown();
    }
}

【问题讨论】:

  • 我建议在 console.neo4j.org 上创建和共享测试图,而不是提供代码来生成测试图。这会很有帮助,而且很容易创建。
  • 已添加。网址是console.neo4j.org/r/7fmo7c
  • 谢谢!这帮助我快速使用它并更接近你想要的。

标签: java nosql neo4j cypher graph-databases


【解决方案1】:
start t1=node(*), t2=node(*) 
where has(t1.type) and has(t2.type) and t1.type='term' and t2.type='term' and id(t1) < id(t2)
with t1, t2 
match t1<-[:HAVE]-doc-[:HAVE]->t2 
where doc.type='document' 
return t1, t2, count(doc)

你可以在这里试试这个:http://console.neo4j.org/r/pshvqx

我希望这是你想要的。此外,为了获得更好的性能,我建议您将索引放在“term”类型的节点上,并在 start 子句中使用索引来获取 t1t2

【讨论】:

  • 或者有一个where id(t1) &lt; id(t2)
  • 好主意@ThomasFenzl !!!非常感谢。那根本没有打动我。用同样的方法更新答案。
  • 这就像一个魅力,但我有索引问题。我不确切知道在哪里(以及如何)放置索引。我从start t1=node:node_auto_index('type:*')... 开始,但似乎不起作用。
  • 如果您稍后启用了自动索引,它将不适用于现有数据。在这种情况下,您需要手动添加现有节点以自动索引或重新创建数据。还要确保在 neo4j.properties 中定义了要自动索引的属性。详情请参考docs.neo4j.org/chunked/milestone/…
  • 另请注意,自动索引是只读索引,即一旦添加到索引中,您就无法从中删除条目。仅当这对您没问题时才进行自动索引。
猜你喜欢
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
相关资源
最近更新 更多