How to stop neo4j creating node if node already exists - c#

I've been fiddeling around with neo4j for the last couple of days, but I keep running
into one issue.
Whenever I run my code it creates an entirely new node.
As seen obove there are two "SELLER" nodes and one "BUYER,SELLER" node.
The node name is "Role" and I'd ideally want it to update if there is already a "Role" node
and only create a new node when there is no "Role" node yet.
Shown below is the query I've written in C# so far, I can't get it to stop creating new nodes.
Hopefully the gods of stackoverflow can help a young lad out. haha
query = query.Merge("(role:Role {roletype: $newRoleValue})")
.Set("role = $newRole")
.WithParam("newRole", new { Name = newTenderVersion.Organization.Role.ToString() })
.WithParam("newRoleValue", newTenderVersion.Organization.Role.ToString())
.Merge($"(organization)-[:HAS_ROLE]->(role)");
=====
EDIT:
query = query.Merge("(role:Role {roleType: $newRoleValue})")
.WithParam("newRoleValue", newTenderVersion.Organization.Role.ToString())
.Merge($"(organization)-[:HAS_ROLE]->(role)");
So I've figured out how to stop the node duplication, now the question remains.
How do I make sure that if an organization is only a SELLER, it will delete its BUYER nodes.

Related

C# Razor query - Using Umbraco V7, how can I check if current page exists as child item in any level 1 content tree nodes?

I have four home nodes for various cultures and host names which are all level 1 in my content tree.
I'm looking to check if the current page exists as a child item in either of those nodes and if so display links, specifically an hreflang tag. (not all child pages exist on every node)
What I've tried so far is creating foreach loops to loop through and it's child items, however so far it only returns me the children for level 1.
IPublishedContent homeOne = Umbraco.TypedContent(1172);
IPublishedContent homeTwo = Umbraco.TypedContent(6093);
IPublishedContent homeThree = Umbraco.TypedContent(7886);
IPublishedContent homeFour = Umbraco.TypedContent(9679);
var pageUrl = CurrentPage.Url().ToString();
foreach (var item in homeOne.Children)
{
var pagePath = item.Url.ToString();
if (pagePath == pageUrl)
{
<link rel="alternate" href="#string.Format("https://www.domain.xx{0}", pagePath)" hreflang="x-default" />
<link rel="alternate" href="#string.Format("https://www.domain.xx{0}", pagePath)" hreflang="en-gb" />
}
}
I then have three similar foreach loops beneath the example above for the other home nodes, interestingly/annoyingly...if I'm on a child page of homeOne, I only see the links generated for homeOne, however if I go to a child page of homeTwo I see the links generated for homeOne and homeTwo. Subsequently visiting homeThree returns links for homeOne and homeThree only.
edit
I should re-iterate that these four root nodes have already set up with cultures and host names and are all in the same language. I'm basically just trying to look at what the current page is, if it exists as a child item across either or all of the four root nodes then show the relevant links
Current Tree Example-
HomeOne
Product1
Product2
HomeTwo
Product1
HomeThree
Product1
Product2
Hope someone can point me in the right direction
Thanks
CurrentPage should have a Path property which contains the IDs of every ancestor. I believe it's a string that you can split by ',' and then see if the resulting array contains either of the homeNode IDs. Something like this: https://coderwall.com/p/gl7poa/active-navigation-in-umbraco
From your code example I can't really figure out what you're trying to do, though. If you are trying to run a classic multilingual setup, have a look at this tutorial - setting it up like this (with domains/hostnames per language) lets Umbraco take care of a lot of the hassle: https://our.umbraco.com/Documentation/Tutorials/Multilanguage-Setup/index-v7
The final solution I found for this was provided via an Umbraco community member, I made some tweaks to the final solution which are documented at the foot of the post below
https://our.umbraco.com/forum/using-umbraco-and-getting-started/100089-query-children-of-multiple-root-nodes-and-return-values-for-hreflang-tags

Trying to do Unwind and Create New Relationship Between Nodes Neo4J C# Client

I have a list of nodes - In the code as targetNodeList and I have a node called sourceNode(Different Types Of Nodes).
The List and the single node are already existing in the neo4j Db
and I would like to make a relationship between them with additional data that is inside the targetNodeList.
TargetNodeList is a wrapper which contains the node data and the relationship data that I would like to put inside the Relationship
I havn't manage to finish the code because I don't know how to continue it but thats the sample that I tried to do :
public void CreateRelationshipBetweenNodes(NodeType sourceNode,List<TargetNodes> targetNodeList,int solutionId)
{
graphClient.Cypher
.Unwind(targetNodeList, "singleNode")
.Match("(firstNode:FirstType)", "(secondNode:SecondType)")
.Where(" firstNode.Id = otherNode:FirstType{Id:innerNode.Id}")
.AndWhere(" secondNode.Id = node:SecondType {Id:singleNode.Id}")
.WithParams(new { innerNode = sourceNode})
.Create("(firstNode)-[msg:SENT {solution}]->(secondNode)")
.WithParam("solution", solutionId).ExecuteWithoutResults();
}
its not working and there is still more data that I want to add to the relationship from the singleNode for example: singleNode.Score
Would appriciate any help.
Thanks a lot from advanced.
So I'm a little confused with the nodes you're taking in and how they relate, but hopefully the below query will get you on the right route.
First off, match on the sourceNode then UNWIND your other nodes, ready to do the create. Once you have the two nodes MATCHed you then CREATE the relationship (PS. you may want MERGE if you don't want duplicates) - and I set an Id property on the relationship - you need to provide a property name, else it won't work!
graphClient.Cypher
.Match("(sourceNode:SourceNodeType {Id:sourceNode.Id})")
.Unwind(targetNodeList, "singleNode")
.Match("(targetNodeInDb:TargetNode {Id:targetNode.Id})")
.Create("(sourceNode)-[:SENT {Id:{solutionIdParam}}]->(targetNode)")
.WithParam("solutionIdParam", solutionId)
.ExecuteWithoutResults();

Trying to do Unwind and Merge on the same command On Neo4J C# Client

I am trying to create a batch of nodes from list but I want to make sure those nodes are not already exists in the neo4j db,
I manage to do it on a single node but I also want to enable it for batch of nodes
I have tried this command:
graphClient.Cypher
.Unwind(NodesList, "singleNode")
.Merge("(node:Node {Id : {innerNode}.Id})")
.OnCreate()
.Set("innerNode= singleNode")
.WithParams("innerNode")
.ExecuteWithoutResults();
and I am getting a error of "Parameter Count Mismatch"
I am still new to Neo4J and I havn't found any one with the same problem at c# language
Thanks a lot from advanced.
I'm assuming that NodesList is a list of the nodes you're wanting to MERGE - in essence, you need to drop the innerNode from your query, and use the singleNode you're passing in from the UNWIND:
graphClient.Cypher
.Unwind(NodesList, "singleNode")
.Merge("(node:Node {Id : singleNode.Id})")
.OnCreate()
.Set("node = singleNode")
.ExecuteWithoutResults();
This should get you there

How to get a second or third XML node when using an anonymous type?

I'm using an anonymous type to grab some XML data. All was going well until I ran across a section of XML where there can be 2 or 3 similar nodes. Like in the XML sample below there are 3 separate "Phones". My code was working fine when there was only ONE element that was possible to grab after following the "element path" I led it to. How can i grab a specific one? Or all 3 for that matter? Handling XML is still new to me and there seems to be soo many ways of handling it Searching the web for my exact need here didn't prove successful. Thanks.
var nodes = from node in doc.Elements("ClaimsSvcRs").Elements("ClaimDownloadRs")
select new
{
Phone1 = (string)node.Elements("Communications").Elements("PhoneInfo").Elements("PhoneNumber").FirstOrDefault(),
Phone2 = (string)node.Elements("Communications").Elements("PhoneInfo").Elements("PhoneNumber").FirstOrDefault(),
};
The XML Code is
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<ClaimsSvcRs>
<ClaimDownloadRs>
<Communications>
<PhoneInfo>
<PhoneTypeCd>Phone</PhoneTypeCd>
<CommunicationUseCd>Home</CommunicationUseCd>
<PhoneNumber>+1-715-5553944</PhoneNumber>
</PhoneInfo>
<PhoneInfo>
<PhoneTypeCd>Phone</PhoneTypeCd>
<CommunicationUseCd>Business</CommunicationUseCd>
<PhoneNumber>+1-715-5552519</PhoneNumber>
</PhoneInfo>
<PhoneInfo>
<PhoneTypeCd>Phone</PhoneTypeCd>
<CommunicationUseCd>Cell</CommunicationUseCd>
<PhoneNumber>+1-715-5551212</PhoneNumber>
</PhoneInfo>
</Communications>
</ClaimDownloadRs>
</ClaimsSvcRs>
</TEST>
I haven't used xpath in a while so i'll let someone else stand in there... but there's a way to select a particular PhoneInfo object based upon its subelements. So if you knew whether you wanted Home or Business or Cell or whatever, you'd be able to select that particular PhoneInfo object. Otherwise if you wanted simple Phone1,2,3 and nulls where ok, use the Skip linq function. Phone2 = query.Skip(1).FirstOrDefault()
lol no worries ;) xpath can be intermixed in here, was my thought, and might be more elegant if your CommunicationUseCd fields were deterministic. Then you could have Home = ... and Work = ..., etc, instead of Phone1 & Phone2
The same could be accomplished by slipping a where clause into each your query lines
If you're up for LINQ you can get all your elements in one go:
foreach(XElement phone in XDocument.Parse(xmlString).Descendants("PhoneInfo"))
{
Console.WriteLine(phone.Element("PhoneNumber").Value);
//etc
}
I find XDocument & LINQ a lot easier than XmlDocument & XPath, if you're okay with the alternative. There's more info on them here

Working with index in Neo4j

I've been going through the Neo4J and Neo4J C# client..
The neo4jclient wiki helped me to with node crud operations.. however the wiki ends there abruptly..
I poked around the test methods in source code and managed to understand about relationships and searched online to understand how indexing works.
So far, here's what I have, roughly:
//create indexing on user and car
client.CreateIndex("User", new IndexConfiguration() { Provider = IndexProvider.lucene, Type = IndexType.fulltext }, IndexFor.Node);
client.CreateIndex("Car", new IndexConfiguration() { Provider = IndexProvider.lucene, Type = IndexType.fulltext }, IndexFor.Node);
//create user
client.Create(new User() { Name = "Dovakiin", Job = "Dragon Slayer" });
client.Create(new User() { Name = "Ulfric stormcloak", Job = "Imperial Slayer" });
//create Car
client.Create(new Car() { Name = "Paarthurnax", Modal = 212 });
//User owns car relationship
client.CreateRelationship(userRef, new Owns_CarRelationship(CarRef));
This is where I am stuck now.. When I try to look for the user by name, my cipher query is returning zero results:
start u=node:User(Name="Dovakiin") return u;
and I don't quite understand why it returns zero nodes when clearly
start n=node(*) return n;
shows all nodes.
Am I missing something else while indexing? Or is this not index related at all? Do I not need to add each node to the index?
All I am trying to do, is select the node with a given property: Name = "Dovakiin" in this case.. How do I select this please?
Just to expand on ulkas' answer, if you want to enable auto indexing and found the documentation a little confusing (like I did the first time I read it), this is how you set it up.
Let's say you want to automatically index some node properties; say, "name" and "job". Open up the /conf/neo4j.properties file and you should see something like this:
# Autoindexing
# Enable auto-indexing for nodes, default is false
#node_auto_indexing=true
# The node property keys to be auto-indexed, if enabled
#node_keys_indexable=name,age
You then have to edit the file to the following:
# Autoindexing
# Enable auto-indexing for nodes, default is false
node_auto_indexing=true
# The node property keys to be auto-indexed, if enabled
node_keys_indexable=name,job
Once this is done, in order for auto indexing to take effect, you'll have to restart neo4j. Also, as a side note, any currently existing nodes won't be auto indexed, which means you'll have to recreate them. If you don't want to start from scratch, here's some documentation on how to update them: http://docs.neo4j.org/chunked/milestone/auto-indexing.html#auto-indexing-update-removal (I've never tried it).
Then you can start finding nodes like this:
start n=node:node_auto_index(name="Dovakiin"), or
start n=node:node_auto_index(job="Dragon Slayer")
Or, like this with the C# client:
Node<User> myNode = client.QueryIndex<User>("node_auto_index", IndexFor.Node, "name:Dovakiin").First();, or
Node<User> myNode = client.QueryIndex<User>("node_auto_index", IndexFor.Node, "job:Dragon Slayer").First();
You can do the same thing with with relationships as well, as soon as you set it up in the /conf/neo4j.properties file. You do it exactly the same way as with nodes.
you must manually add the nodes to the index, something like
client.indexRef1.addToIndex(nodeRef, 'name', 'Dovakiin')
client.indexRef2.addToIndex(nodeRef, 'job', 'Dragon Slayer')
there is also an automatic indexing feature in neo4j in case you want the nodes to be automatically added to the index.

Categories