Disruptive error: the `USE` command doesn't run correctly

I'm running neo4j enterprise server 5.26.1 with browser 5.26.2

I have two graphs: one named neo4j and the other named gdpr.

In the browser, I'm positioned on the Neo4j Database.

When I run the following query

the result seems 0 as expected, but it is on the wrong DB: it emptyed the Neo4j DB and not the gdpr DB as you could see in the following image:

So, it is my fault or the neo4j one?

From your other thread, have you tried:

call {
    use gdpr
    
   ... CYPHER ...
}

I tryed the following:

AS my gdpr DB is also part of a composite database, I tried with the composite db also, but the result was not correct:

and the gdpr DB is always full of nodes as you can see

Are you using the dropdown list to select the database, then executing the query in the resulting editor that shows the database name as the prompt? Your results can be explained if you ran the query in the editor that is set to use the wrong database.

So, the basic question is:

Can I programmatically change the master database where I'm running?

Without being constrained to choose it in the dropdown list?

At me, this situation looks like the composite database is not mature enough and can easily bring to disaster in the other databases!

The dropdown list is just a simple means of executing the ':USE ' command, instead of manually typing it. You need to make sure you run your query in the new editor that is created that has the prompt with the database name in it. All previous editors don't change, so you cannot just go rerun those assuming they will use the new database.

I think this is an issue when using the browser. It seems you can't start the query with a "USE " to switch to the composite database, then run a query with multiple databases, as it thinks you are running the database in the one identified in the prompt. In the browser, you need to switch the editor to the composite database, then run the query in that editor. I don't think this is an issue when using a driver, as you can create a session and specify to use the composite database in the session configuration. You can then run your query utilizing database's that are part of the composite database. I have not tried this though.

BTW- it does seem that the 'USE database' at the start of your query does not switch the database, so you query still runs agains the database identified in the editor's prompt. This would explain why you deleted the nodes in the wrong database. I was able to reproduce this.

I agree that this seems unintuitive and dangerous.

Now I am confused. I tried it again and now it is working as you would expect. I am not sure what changed. In the simulation, I created some nodes in db1 and ran the query in a db1 editor that started with USE db2, then deleted nodes. Initially this was deleting the nodes in db1 when the editor prompt was db1, but now it is not.

USE db2
match(n) delete n

This (obviously) run, because I don't pass nodes to a call and not use WITH x AS y:

but the manual asserts that Updates can only be performed on a single constituent graph per transaction.

How can we ask Neo4j developers on how to implement the above assertion and make an update in just one designed database?

And this is another crazy example: can someone tell me how to use federateddatabases in neo4j???

I reach the following conclusion: federatedDBs cannot be used safely with Cypher but only with external drivers.

This is not a good signal from neo4j developers.

You can't import the node 'n' to the second subquery that uses a different database. It wouldn't be useful in a query on another database, as the node that the variable would be bound to can't be accessed by the other database. The way to handle this is to pass specific information about the node that you can use in the second subquery, such as the node's label and/or properties.

Try something like this:

In the example you are showing, the second 'call' is nested within the first subquery. This is not allowed, since the outer query specifies the database. All following queries must use the same database as the outermost query.

some things, only somehow, look reasonable.

But my Use Case is the following:

I have a GDPR database containing all the reserved data for a User|Customer. I want to access that DB and return a vnode, containing just the uuid and the nickaname of the subject. Then I want to save these 2 data in the other DB to be used later

I'm convinced that it can be only obtained using an external piece of code (python, node?) and save these info in a session block.

The second thing:

I want to read from the first db and later write other things to a second: how can I accomplish that if I cannot change my db? How can i designate the only write DB?

Maybe with a call IN TRANSACTION?

I think this mimics your use case.

call {
    use comp.alias_db1
    match(n:Customer)
    return n.uuid as uuid, n.nickname as nickname
}
call {
    use comp.alias_db2
    with uuid, nickname
    create(m:Customer{uuid: uuid, nickname: nickname})
    return m
}
return m

In the following, there are two Customer nodes in the db1 database and zero Customer nodes in the db2 database. The query retrieves the two Customer nodes for db1 and creates nodes in db2 using the node's UUID and nickname properties.

Well, this looks to tun correctly.

But now, how can we push ahead another little step?

In the step 1 you read just one exact node from the DB1.

what if you want to retrieve all customers, or all nodes which correspond to certain characteristics at all? (example: all nodes with a specific attribute, or in relation with another specific node like MATCH (m)-[r:BELONGS_TO]->(x:Customer). )

and the replicate them in the second db .... how to pass labels(m) and properties(m) to the second query?

This is exactly my goal

Using this test data:

create(n:Customer{id:0, nickname: "minnie"})
create(n)<-[:BELONGS_TO]-(:Item{name:"bike"})
create(n)<-[:BELONGS_TO]-(:Item{name:"glove"})
create(n)<-[:BELONGS_TO]-(:Item{name:"hat"})
create(m:Customer{id:1 nickname: "mickey"})
create(m)<-[:BELONGS_TO]-(:Item{name:"jacket"})
create(m)<-[:BELONGS_TO]-(:Item{name:"coat"})

Initial state of db1:

Initial state of db2:

Query:

call {
    use comp.alias_db1
    match(n)<-[:BELONGS_TO]-(m)
    return 
        properties(n) as properties_n, labels(n) as labels_n,
        properties(m) as properties_m, labels(m) as labels_m
}
call {
    use comp.alias_db2
    with properties_n, labels_n, properties_m, labels_m
    merge(x:$(labels_n){id: properties_n.id})
    merge(y:$(labels_m){name: properties_m.name})
    merge(x)<-[:BELONGS_TO]-(y)
}

Query execution in composite db:

db2 state after executing 'copy' query in composite database:

Does this meet your needs? Note, I could have not specified the relationship type and passed it through to the second call subquery to create the relationship with the correct type.

hmm, it is a step ahead,

next step (maybe the latest: how to copy all the properties of properties_n and properties_m (i don't know which are the properties of any node! as id or name.

You can set all the properties with the following:

Set x = properties_n
Set y = properties_m

But you will need primary keys to drive the merges.

Hi Gary, this is the solution I needed.

The primary key is already settled, because for each different nodes the constraint will be declared in both the DB, I just don't know which kind of node I'll managing at every call.

Well, thank you, as always you find the right solution.

At the next one!

1 Like

@glilienfield , this example is with DB 5.27.0 Enterprise

I was so happy with the solution, but there is something already not running as (I) expected !

I have this gdpr graph, which is part of the federatednotions one.

this is a direct query result:

as you can see, there are exactly 18 nodes into the gdpr graph.

Now, I run this query with the idea to empty my gdpr database:

The result is that nothing seems to happen, and if I query again the federatednotions.gdpr, it results. with all the nodes, as at the beginning.

As the manual states 'you can use just one graph in a write query, I just used only the federatednotions.gdpr

Can you see something wrong? Where is the error?

The result of your first query is showing only nodes, no relationships. Unless you have the default behavior turned off (default is to "connect result nodes"), I am deducing you don't have any relationships. Oh, I just saw in the left-hand pane it states "no relationships in the database", so I was correct. Because of this, your match (n)-[r]-(m) returned zero results, thus the query stopped.

Just a note, you don't need to use the composite database if you are not querying for data in more than one database. In your case as presented, you can execute the deleting in the 'gdpr' database directly (well, the database that is aliased by 'federatednotions.gdpr'.

You can use two techniques to delete all nodes/relationships in a graph. One is to create/replace the graph or match all nodes and detach delete them.

Execute either of the two in the gdpr database:

create or replace database gdpr
match(n) detach delete n