¿Neo4j verifica si el nodo existe antes de crear?

Tengo la sensación de que estoy haciendo todo mal. Pero de todos modos.

Tengo una base de datos sql que tiene esencialmente una tabla desnormalizada a propósito que he construido para facilitarme esta tarea, por lo que solo puedo tomar cosas de una tabla.

Lo que tengo es una tabla de pares, algo así:

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

Y así sucesivamente.

Entonces, para mi base de datos gráfica neo4j, quiero que cada ID de usuario sea un nodo, las otras cosas no son demasiado importantes, pero serán básicamente las cosas en las relaciones.

Solo quiero un nodo para cada usuario, por lo que siento que si hago algo como esto:

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

Que cuando agregamos el nodo con user_id 1234 por segunda vez, solo creará un nuevo nodo, pero lo que quiero es que solo tome este nodo en lugar de crearlo para poder agregarlo a la relación a 1080 en este caso.

Entonces, ¿cuál es la forma de hacer esto?

preguntado el 12 de junio de 12 a las 16:06

6 Respuestas

Has mirado CREAR ÚNICO?

Si no puede usar Cypher, tal vez pueda usar nodos únicos?

Respondido el 08 de diciembre de 12 a las 19:12

Sí, esto funciona absolutamente, por ejemplo, si usa merge(n:State {name:"LoadAd"}); solo creará el nodo si existe. - seansanders

Utilice un índice para buscar y, si no encuentra ningún resultado, cree uno nuevo.

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

¿Es este el tipo de operación que está buscando?

Respondido el 13 de junio de 12 a las 03:06

Eso podría funcionar. ¿Es esto más rápido o más lento o lo mismo que el método get o ccreate vinculado por Andres? Parece que hacen lo mismo de diferentes maneras, pero todavía no entiendo cómo funcionan los índices en neo4j. - tom carrick

Me imagino que la indexación sería más rápida, ya que la indexación generalmente está destinada a una búsqueda rápida. - Nicholas

No sé si estoy leyendo mal los documentos, pero ¿no obtiene o crea un índice de todos modos? Estoy confundido. - tom carrick

Indexa el ID de nodo o relación, pero todo lo demás que necesitará para crear su propio índice para cualquier otra cosa que desee indexar. - Nicholas

No funciona, incluí un SSCCE en stackoverflow.com/questions/42255542/… - sarah.ferguson

Probablemente querrás usar el UniqueNodeFactory proporcionada por Neo4j.

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

Respondido el 13 de junio de 12 a las 23:06

Normalice sus tablas SQL para que parezcan nodos y relaciones. Luego, con cypher en su migración, puede hacer que la migración se pueda volver a ejecutar con algo como

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

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

para nodos y dado que debería tener en su tabla intermedia de muchos a muchos:

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

ahora terminará sin duplicados y podrá volver a ejecutar tanto como desee.

Respondido 12 Abr '13, 14:04

use esta función: donde: ID es la clave que desea verificar si ya existe Tipo: es el tipo del nodo (la etiqueta) esta función creará el nodo y lo devolverá, luego puede agregar más propiedades.

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

Respondido el 06 de junio de 15 a las 17:06

usando la consulta de cifrado, puede crear un nodo único con la siguiente sintaxis,

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

al hacer una llamada REST, uno puede hacer una inserción por lotes como

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

De manera similar, para crear relaciones en una solicitud por lotes, haga lo siguiente

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

Respondido el 14 de junio de 13 a las 16:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.