Neo4j在创建之前检查节点是否存在?

时间:2012-06-12 15:21:09

标签: java neo4j

我有一种感觉,我认为这一切都错了。但无论如何。

我有一个sql数据库,它本质上是一个有目的的非规范化表,我已经构建了这个表,这对我来说这个任务更容易,所以我可以从一个表中获取东西。

我所拥有的是成对的表格,如下所示:

user_lo | user_hi | something_else | other stuff
1000    | 1234    | 1231251654     | 123
1050    | 1100    | 1564654        | 45648
1080    | 1234    | 456444894648   | 1

等等。

因此,对于我的neo4j图形数据库,我希望每个用户ID都是一个节点,其他的东西不是太重要,但基本上就是关系中的东西。

我只想为每个用户提供一个节点,所以我的感觉是,如果我做这样的事情:

while (rs.next()) {
    node_lo = db.createNode();
    node_lo.setProperty("user_id", rs.getInt(1));
    node_hi = db.createNode();
    node_hi.setProperty("user_id", rs.getInt(2));
}

当我们第二次添加带有user_id 1234的节点时,它只会创建一个新节点,但我想要的是它只是抓住这个节点而不是创建它所以我可以将它添加到关系中在这种情况下为1080。

那么这样做的方法是什么?

6 个答案:

答案 0 :(得分:4)

使用索引进行搜索,如果没有找到结果,则创建一个新索引。

Index<Node> userIndex = graphDatabaseService.index().forNodes('UserNodes');

IndexHits<Node> userNodes = userIndex.get('id', 1234);

if(!userNodes.hasNext()){
    //Create new User node
} else {
    Node userNode = userNodes.next();
}

这是您正在寻找的操作类型吗?

答案 1 :(得分:2)

你看过CREATE UNIQUE吗?

如果你不能使用Cypher,也许你可以使用unique nodes

答案 2 :(得分:2)

您可能想要使用Neo4j提供的UniqueNodeFactory

    public Node getOrCreateUserWithUniqueFactory( String username, GraphDatabaseService graphDb )
{
    UniqueFactory<Node> factory = new UniqueFactory.UniqueNodeFactory( graphDb, "UserNodes" )
    {
        @Override
        protected void initialize( Node created, Map<String, Object> properties )
        {
            created.setProperty( "id", properties.get( "id" ) );
        }
    };

    return factory.getOrCreate( "id", id );
}

答案 3 :(得分:1)

将SQL表规范化为看起来像节点和关系。然后在迁移中使用cypher,您可以通过

之类的内容重新运行迁移
start a = node:node_auto_index('id:"<PK_Value>"')
delete a

create a = {id: "<PK_VALUE>", etc}

表示节点,因为你应该在多对多中间表中使用:

start LHS = node:node_auto_index('id:"<LHS_PK>"'),
      RHS = node:node_auto_index('id:"<RHS_PK>"')
create unique LHS=[:<relType> {<rel props>}]->RHS

现在你最终没有重复,可以随心所欲地重新运行。

答案 4 :(得分:1)

使用此功能: 哪里: ID是您要检查的密钥(如果已存在) 类型:是节点的类型(标签) 此函数将创建节点并将其返回,然后您可以添加更多属性。

public static Node getOrCreateUserWithUniqueFactory( long ID, GraphDatabaseService graphDb, String Type )
{
    UniqueFactory<Node> factory = new UniqueFactory.UniqueNodeFactory( graphDb, Type )
    {
        @Override
        protected void initialize( Node created, Map<String, Object> properties )
        {

            created.addLabel( DynamicLabel.label( Type ) );
            created.setProperty( "ID", properties.get( "ID" ) );
        }
    };

    return factory.getOrCreate( "ID", ID );
}

答案 5 :(得分:0)

使用cypher查询,您可以使用以下语法

创建唯一节点
CYPHER 2.0 merge (x:node_auto_index{id:1})

进行REST调用时,可以像

那样进行批量插入
$lsNodes[] = array(

            'method'=> 'POST', 'to'=> '/cypher',

            'body' => array(
                'query' => 'CYPHER 2.0 merge (x:node_auto_index{id_item:{id}})',
                'params'    =>  array('id'=>1)
            ),
            'id'=>0

        );

        $sData = json_encode($lsNodes);

类似于在批处理请求中创建关系,请执行以下操作

$lsNodes[] = array(

                        'method'=> 'POST', 'to'=> '/cypher',

                        'body'  => array(
                            'query'     => 'start a=node:node_auto_index(id={id1}), b = node:node_auto_index(id={id2}) create unique a-[:have{property:30}}]-b;',
                            'params'    => array(
                                'id1'  => 1, 'id2'=>  2
                            )
                        ),
                        'id'    => 0

                    );
$sData = json_encode($lsNodes);