I am storing Hierarchy data in Neo4j. I want to store history of the Node. Consider I have a label called GROUP and the earlier name was "MARKETING" now it has been changed to "MARKET123". So i want to create a new node where the name will be MARKET123 and the create a relationship with other connected node same as for the older node named "MARKETING"...
But all this i want to do dynamically instead of passing the other Nodes name and the relationship value in the cypher query.
Please suggest me how it can be done.
You can add versioning to your graph nodes.
Here is a graph gist about time-based versioning that you may adapt to your needs.
http://www.neo4j.org/graphgist?608bf0701e3306a23e77
Related
I am new to Neo4j and am referring to this tutorial.
I am not finding any answer on how to fetch the node name using CQL.
For example:
If I create two nodes like so:
CREATE (Dhawan:player{name: "Shikar Dhawan", YOB: 1985, POB: "Delhi"})
CREATE (Ind:Country {name: "India"})
and then build relationship at a later date using:
CREATE (Dhawan)-[r:BATSMAN_OF]->(Ind)
How do we know the node name: Dhawan or Ind?
Using:
MATCH (n) RETURN n
I am getting back the label name but not the node name!
How do I get all the details of an existing graph DB?
The thing you're calling "the node name" is actually a variable, and is only present for the duration of a single query (or less, if you don't include it in a WITH clause and it goes out of scope). It is never saved to the graph db, and is not persisted data.
In your example, you would only be able to use CREATE (Dhawan)-[r:BATSMAN_OF]->(Ind) (and have those variables refer to your previously created nodes) if the create was performed in the same query where those variables were previously bound (and still in scope).
Otherwise, this would create two new nodes, create the :BATSMAN_OF relationship between them, and bind those variables to the new nodes for the duration of their scope.
I know how this would be accomplished in SQL but having difficulty wrapping my brain around how to do this in cypher..
Basically working on a master data setup where a user has a master_id (node) and need to use an existing relationship property to determine the master_id in order to create a new relationship between the master_id node and a location node.
Currently have master users created as nodes that contain a master_id property. A relationship is created between the master user and a brand, and the relationship has a property of brand_user_id.
I now have another file I need to import that contains data at the brand_user level, but need to create the relationship between the master_id and a location node. In order to do this because the file does not contain the master_id property, I am attempting to use the new file to lookup master_id's based on the existing relationship with the brand, then use that master_id to create the new relationship with the location.
Have this relationship:
(m:Master{master_id:12345})-[:IS_BRAND_USER{brand_user_id:9876}]->(b:Brand{name:"Acme"})
Have this file:
brand_user_id,location_id
9876,6
Need this relationship:
(m:Master{master_id:12345})-[:HAS_LOCATION]->(l:Location{id:6})
My approach:
LOAD CSV WITH HEADERS FROM "file:///brand_user_ids.csv" as buid
MATCH (m:Master)-[r:IS_BRAND_USER{brand_user_id:buid.id}]->(b:Brand)
WITH m, buid.location_id AS location_id
MATCH (l:Location {id: location_id})
CREATE (m)-[:HAS_LOCATION {source: 'abcdef'}]->(l)
Seems to run for an extremely long time and not seeing any real progress after an hour so I'm wondering if this is fundamentally the correct approach or not, or if I have inadvertently created some horrific cross join equivalent.
The problem is that you are trying to enter a graph on a relationship. And that always requires lots of "scanning the graph".
Now, I'm not a specialist in your domain, but you might be missing a type of nodes here ... BrandUser. And there could be several reasons for that :
Based on your data a Master can have many BrandUser id's. Potentially even more than one per Brand ? Do you have other properties that make sense on the BrandUser level ?
That Location data is strange. Wouldn't you agree it's actually the BrandUser that has a location and that a Master may have many locations ?
The most important reason is however ... if you're going to enter the graph on the brand_user_id all the time (and judging from the location example that may be the case) ... you've got the reason to turn it into a node right there.
So ... it's a modeling issue really.
Hope this helps.
Regards,
Tom
I'm using Neo4j Community edition 2.1.4. I have hierarchy of 4 levels and each level names i have treated it as label name for that level.So in my graph i have totally 4 labels. Now for the first time I have loaded csv file into neo4j and using MERGE and CREATEkeywords created the nodes and relationships. In future the requirement is like
scenario 1:
if someone wants to rename the hierarchy level name to some new name, then I have to
change the label name to a new name.
Scenario 2:
if any of the property name of node changes to to new name
In the both the cases i wanted to track the history of the node. How can i do it? So that in future someone wants to see the history details , they can query and get the details.
So how can i track the history details of the nodes in neo4j?
My Approch:
For the first time i will load the csv file and create nodes and relationships. Then if someone wants to change the label name of node A(level name which is standard) which is having a properties like ID, name,start_date,end_date,Status.Then i will replicate the node A with all the properties and change the status to inactive and i will overwrite the old node with the new details. But i'm clueless whether this solution is going to work or not. Also i have more thane 10000 nodes in my db.
So please suggest me a better approach to track the nodes history.
Have a look at the GraphAware ChangeFeed Module. You can track history of changes and also configure which changes you would like to track and which to ignore.
You can use versionning. Examples in this blog post : neo4j.org/graphgist?608bf0701e3306a23e77 that you can adapt for your needs
In my recent question, Modeling conditional relationships in neo4j v.2 (cypher), the answer has led me to another question regarding my data model and the cypher syntax to represent it. Lets say in my model, there is a node CLT1 that is what I'll call the Source node. CLT1 has relationships to other 286 Target nodes. This is a model of a target node:
CREATE
(Abnormally_high:Label1:Label2:Label3:Label4:Label5:Label6:Label7:Label8:Label9:Label10
{Pro1:'x',Prop2:'y',Prop3:'z'})
Key point: I am assuming the string after the CREATE clause is
The ID of this target node
The ID is significant because its content has domain-specific meaning
and is query-able.
in this case its the phrase ...."Abnormally_high".
I made this assumption based on the movie database example.
CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})
CREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967})
The first strings after CREATE definitely have domain-specific meaning!
In my earlier post I discuss Problem 2. I find that problem 2 arises because among the 286 target nodes, there are many instances where there was at least one more Target node who shares the identical ID. In this instance, the ID is "Abnormally_high". The other Target nodes may differ in the value of any of Label1 - Label10 or the associated properties.
Apparently, Cypher doesn't like that. In Problem 2, I was discussing the ways to deal with the fact that cypher doesn't like using the same node ID multiple times even though the labels or properties were different.
My problem are my assumptions about the Target node ID.
AM I RIGHT?
I am now thinking that I could instead use this....
CREATE (CLT1_target_1:Label1:Label2:Label3:Label4:Label5:Label6:Label7:Label8:Label9:Label10
{name:'Abnormally_high',Prop2:'y',Prop3:'z'})
If indeed the first string after the CREATE clause is an ID, then all I have to do is put a unique target node identifier.... like CLT1_target_1 and increment up to CLT1_target_286. If I do this, then I can have the name as a property and change whatever label or property I want.
Do I have this right?
You are wrong. In Cypher, a node name (like "Abnormally_high") is just a variable name that exists for the lifetime of the query (and sometimes not even that long). The node name used in a Cypher query is never persisted in any way, and can be any arbitrary string.
Also, in neo4j, the term "ID" has a specific meaning. The neo4j DB will automatically assign a (currently) unique integer ID to each new node. You have no control over the ID value assigned to a node. And when a node is deleted, neo4j can reassign its ID to a new node.
You should read the neo4j manual (available at docs.neo4j.org), especially the section on Cypher, to get a better understanding.
I'm using neo4j server versiĆ³n 1.8. The current requirement of my application is to create and/or update multiple nodes and add them to a specific index (all in one request). We have several indexes, and one node can be in some of them. Those nodes have a property that is a ID (significant for our application). If there is already a node with that ID, we only need to override its properties. What we now do is to first check which of these nodes exist (via GET in the index that contains all the nodes) and stored in a data structure. Then I make the batch request to create or update the nodes. If the ID does not exist in the data structure, we have to create a node. Otherwise, only we have to update its properties. This is slow, it is best to make a batch request only, instead of two. I try with UNIQUE INDEXES but the node can be in several indexes. What do you recommend I do?