i am using neography as wrapper of the REST api for Neo4j graph database.
I often need to change the end node of a relationship, but i am not able to do this using neography.
Of course, i can delete the relation then recreate it with the new end point node, but it's not optimized.
Does anyone had this problem?
Thanks.
Neo4j does not allow replacing the nodes of a relationship (see javadoc). So you only can create a new relationship to the new end node and delete the other relationship.
Related
I'm going to try in my application Neo4j Manual Index on Relationship Properties in order to fix the performance issue I faced Neo4j Cypher query performance optimization
I have a few question which is not clear to me from the official Neo4j documentation:
MATCH (:Flight)-[r:DESTINATION]->(:Airport)
CALL apoc.index.addRelationship(r,['taxi_time'])
RETURN count(*)
The statement will create the relationship index with the same name as
relationship-type, in this case DESTINATION and add the relationship
by its properties to the index.
When do I need to create this relationship index? It should be done once(let's say at the application startup) or do I need to invoke this APOC function each time new -[r:DESTINATION]-> relationship is added between Flight and Airport nodes?
In case of existing -[r:DESTINATION]-> relationship update, how to update this information in the appropriate manual index?
In case of deleting some of Flight or Airport node - do I need to manually find and remove appropriate -[r:DESTINATION]-> relationships from the manual index or it will be done automatically by APOC and Neo4j?
In case of Spring Data Neo4j project - how to properly execute queries that contain APOC functions? For example, I want to call apoc.index.addRelationship in order to create the manual index for the relationship properties. Can I use org.neo4j.ogm.session.Session.query for this purpose?
What the consistency model is used for the manual indexes - Do they use eventual consistency or strong consistency model between the index and the original data?
I agree Neo4J documentation on this issue is really insufficient.
To answer your questions:
1.If you upgraded your Neo4J from an older version that used automatic relationship index you would need to run APOC (only once) to index your existing relationships using something like
MATCH ()-[r]->() CALL apoc.index.addRelationship(r,['property_1','property_2']) RETURN count(*);
You would then need to set up a trigger to any new relationship you add to that index, running something like this once:
CALL apoc.trigger.add('RELATIONSHIP_INDEX',"UNWIND {createdRelationships} AS r MATCH ()-[r]->() CALL apoc.index.addRelationship(r,['property_1','property_2']) RETURN count(*)", {phase:'after'})
(you will need to activate apoc.trigger.enabled=true in neo4j.conf file before)
2.See above
3.You would need to remove them also from the index, it is not done automatically. Set up an APOC trigger with removeRelationshipByName() for that.
4.Should be possible.
5.Somebody from Neo4J should answer this.
Hope this helps and saves you some time!
I'm pretty new to Neo4j and graph DBs in general, and have been playing around with it for the last few days. I've now hit something I'm stumped on: I'm trying to create a "temporary" relationship between two disjoint nodes just for the sake of a RETURN, then not store this relationship within the DB afterwards.
The dataset I'm using is a graph of Movie and Person nodes provided in one of the basic Neo4j built-in tutorials. My query is currently as follows:
MATCH (p1:Person)-[r1:ACTED_IN]-(m1:Movie)-[r2:ACTED_IN]-(p2:Person)
WHERE p1.name="Kevin Bacon"
RETURN {start:p1,rel:"COSTAR",end:p2}
What I'd ultimately like to see is a central "Kevin Bacon" node with COSTAR relationships to a series of Person nodes around it, without any Movie nodes or ACTED_IN relationships being displayed. The query above does show the COSTAR relationship in the returned rows, but it does not appear on the graph itself; I've attached a few screenshots of what I'm seeing.
The only other idea I have is to use the MERGE keyword to create a COSTAR relationship, but (as I understand it) this actually stores the relationship in the DB which is what I'm trying to avoid.
Any suggestions would be greatly appreciated.
The neo4j Browser only visualizes nodes and relationships that actually exist in the DB. So, there is no way to do what you want without actually creating the COSTAR relationships, visualizing the result in the Browser, and then deleting all the COSTAR relationships.
As a workaround you could simply display the nodes of all of Kevin Bacon's costars, like this:
MATCH (p1:Person)-[:ACTED_IN]-(:Movie)-[:ACTED_IN]-(p2:Person)
WHERE p1.name="Kevin Bacon"
RETURN DISTINCT p2;
So you want the relationships to appear in the graph visualization in the Neo4j browser but not store these relationships in the graph itself? I can't think of a way to make that happen (without hacking it), but would deleting the relationships after you are done generating the visual work?
Query to create COSTAR relationships:
MATCH (p1:Person)-[r1:ACTED_IN]-(m1:Movie)-[r2:ACTED_IN]-(p2:Person)
WHERE p1.name="Kevin Bacon"
CREATE UNIQUE (p1)<-[:COSTAR]-(p2);
Execute your query to populate the graph in Neo4j Browser...
Then to delete the COSTAR relationships:
MATCH (:Person)-[r:COSTAR]-(:Person)
DELETE r;
The best way to achieve this (now... 6 years later) is with the gds.graph.create.* functions (assuming you load GDS)
https://neo4j.com/docs/graph-data-science/current/graph-create/
With a graph as simple as this, gds.graph.create(...) would be enough (creating COSTAR for all co-starrings)
Or, if you wanted to do some constraining, gds.graph.create.cypher(...)
The in-memory graph projection feels like what you wanted to achieve - it persists only as long as the DBMS is active, or until you call gds.graph.drop(...)
Using Neo4j 2.1.4 and SDN 3.2.0.RELEASE
I have a graph that connects nodes with relationships that have a UUID associated with them. External systems use the UUID as a means to identify the source and target of the relationship. Within Spring Data Neo4j (SDN) we have a #RelationshipEntity(type=”LINKED_TO”) class with a #StartNode, #EndNode and a String uuid field. The uuid field is #Indexed and the resulting schema definition in Neo4j shows up as
neo4j-sh (?)$ SCHEMA
==> Indexes
...
==> ON :Link(uuid) ONLINE
...
However, running a cypher query against the data, e.g.
MATCH ()-[r:LINKED_TO]->() WHERE uuid=’XXXXXX’ RETURN r;
does a full scan of the database and takes a long time
If I try to use the index by running
MATCH ()-[r:LINKED_TO]->() USING INDEX r:Link(uuid) WHERE uuid=’XXXXXX’ RETURN r;
I get
SyntaxException: Type mismatch: expected Node but was Relationship.
As I understand it, Relationships are supposed to be first class citizens in Neo4j, but I can’t see how to utilize the index on the relationship to prevent the graph equivalent of a table scan on the database to locate the relationship.
I know there are posts like How to use relationship index in Cypher which ask similar things, but this Link is the relationship between the two nodes. If I converted the Link to a Node, we would be creating a Node to represent a Relationship which seems wrong when we are working in a graph database - I'd end up with ()-[:xxx]->(:Link)-[:xxx]->() to represent one relationship. It would make the model messy purely due to the fact that the Link couldn't be represented as a relationship.
The Link has got a unique, shared key attached to it that I want to use. The Schema output suggests that the index is there for that field - I just can't use it.
Does anyone have any suggestions?
Many thanks,
Dave
Schema indexes are only available for nodes. The only way to index relationships is using legacy indexes or autoindexes. Legacy indexes need to be used explicitly in the START clause:
START r=relationship:my_index_name(uuid=<myuuid>)
RETURN r
I'm not sure how this can be used in conjunction with SDN.
side note: requiring relationship index is almost always a indication of doing something wrong in your graph data model. Everything being a thing or having an identity in your domain should be a node. So if a relationship requires a uuid, maybe the relationship refers to a thing and therefore should be converted into a node having a inbound relationship to the previous start node and a outbound relationship to the previous end node.
We have selected neo4j as the DB for our web application. The user has a large number of relations and connected nodes. As of now there are about 20 relations for a user. One of the features is a newsfeed feature. If i want to delete a user completely, is the cypher query the best way to delete or is there any other alternative?
Since we are still planning to add new features, the relationships and nodes connected to the user also will increase. So if we use cypher query, the query has to be modified for every new relationship added. Please advise.
Thanks,
Pavan
Yes, you can use Cypher to remove a user. Of course, there are alternative methods, depending on the language or framework you're using with your web application. If you like to have advise on that, please specifiy how you're using Neo4j in detail.
Note that you have to remove all relationships (outgoing and incoming) first in order to be able to remove the node.
Example:
START n = node(3)
MATCH n-[r]-()
DELETE n, r
This example was taken from the official manual: http://docs.neo4j.org/chunked/milestone/query-delete.html
As of Neo4j 2.3 there is another way to do this:
MATCH (n { name:'Andres' })
DETACH DELETE n
I found this example in the documentation at: http://neo4j.com/docs/stable/query-delete.html
An alternative could be to write a gremlin script that traverses your graph starting with your user and is putting in two collection the relationships and the nodes that you intend to delete. If you want to delete everything, perhaps you can implement your depth first traversal in Gremlin and delete while traversing.
I have created a relationship (for example "KNOWS") between 2 nodes on the Neo4j webAdmin application. If I want to rename the relationship (from "KNOWS" to "LOVES"), how can I do it?
The solution I have so far is delete the "KNOWS" relationship and create a new "LOVE" relationship.
Is there any easier way to do this?
Thanks,
Yes, that is how you do it. In the cypher console, you can do
start n=node(1) match n-[r:KNOWS]->m create n-[:FRIEND]->m delete r
see http://tinyurl.com/7umvpro for an example.
If you are using the Embedded neo4j then renaming is not possible. For this, you'll have to delete the existing relationship b/w nodes and then create new relationship b/w same nodes again.
Make sure you all do this in a transaction.
Regards,
Sushil Jain
Click here