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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10999730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:21:22  来源:igfitidea点击:

Neo4j check if node exists before creating?

javaneo4j

提问by Tom Carrick

I have a feeling I'm going about this all wrong. But anyway.

我有一种感觉,我在做这一切都是错误的。但无论如何。

I have an sql database which has essentially a purposefully denormalised table which I've constructed to make this task easier for me, so I can just grab stuff from one table.

我有一个 sql 数据库,它本质上有一个故意非规范化的表,我构建它是为了让我更轻松地完成这项任务,所以我可以从一个表中获取内容。

What I have is a table of pairs, something like this:

我有一个成对表,如下所示:

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

And so on.

等等。

So for my neo4j graph db, I want each user id as a node, the other stuff isn't too important but will be the stuff in the relations basically.

所以对于我的 Neo4j 图数据库,我希望每个用户 ID 作为一个节点,其他的东西不是太重要,但基本上是关系中的东西。

I only want one node for each user, so my feeling is that if I do something like this:

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

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));
}

That when we add the node with user_id 1234 for the second time, it will just create a new node, but I what I want is for it to just grab this node instead of creating it so I can add it to the relationship to 1080 in this case.

当我们第二次添加 user_id 为 1234 的节点时,它只会创建一个新节点,但我想要的是它只是抓取这个节点而不是创建它,这样我就可以将它添加到 1080 的关系中这个案例。

So what is the way to do this?

那么有什么方法可以做到这一点呢?

采纳答案by Andres

Have you looked at CREATE UNIQUE?

你看过CREATE UNIQUE吗?

If you can't use Cypher, maybe you can use unique nodes?

如果您不能使用 Cypher,也许您可​​以使用唯一节点

回答by Nicholas

Use an index to search, and if no result of found, create a new one.

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

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();
}

Is this the type of operation you are looking for?

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

回答by Michael Hunger

You'll probably want to use the UniqueNodeFactoryprovided by Neo4j.

您可能想要使用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 );
}

回答by Shannon Monasco

Normalize your SQL tables to look like nodes and relationships. Then with cypher in your migration you can make the migration rerunnable by something like

规范您的 SQL 表,使其看起来像节点和关系。然后在迁移中使用密码,您可以通过类似的方式使迁移重新运行

start a = node:node_auto_index('id:"<PK_Value>"')
delete a

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

for nodes and since you should have in your many-to-many middle table:

对于节点,因为你应该在你的多对多中间表中:

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

now you will end up with no duplicates and can rerun as much as you like.

现在您将不再有重复项,并且可以随心所欲地重新运行。

回答by Wesam Na

use this function: where: ID is the key which you want to check if already exist Type: is the type of the node ( the label) this function will create the node and return it, then you can add more properties.

使用这个函数: 其中: ID 是要检查是否已存在的键 Type: 是节点的类型(标签) 此函数将创建节点并返回它,然后您可以添加更多属性。

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 );
}

回答by Burhan

using cypher query, you can create a unique node with the following syntax,

使用密码查询,您可以使用以下语法创建一个唯一的节点,

CYPHER 2.0 merge (x:node_auto_index{id:1})

when making a REST call, one can make batch insertion like

在进行 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);

similarly for creating relationships in a batch request, do the following

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

$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);