I am using neo4js to store users as nodes with property as user_id. There is a friend relation from user1 to user 2.
I am trying to find the incomming friend connections on node user2(user_id =2) which are comming from node with user_id=1.
I am using the neography library for the same.
https://github.com/maxdemarzi/neography/
u2 = Neography::Node.(id)
u2.outgoing(:friends).filter("..........")
I am not sure what exact filter should be given so that I can filter out the relationships comming from node(s) with user_id=1.
Regards,
Pankaj
You can use a traversal in neo4js to find those relationships.
This is untested code, but you want to do something like this:
var promise = somenode.traverse({
"prune_evaluator": {
"language": "javascript",
"body": "position.endNode().getId()!=2;" // Note that this is a string
}},
neo4j.traverse.RETURN_RELATIONSHIPS);
promise.then(function(relationships) {
console.log(relationships);
});
The first argument to the traverse method is a traversal object, for full docs on what you can put there, see http://docs.neo4j.org/chunked/snapshot/rest-api-traverse.html
Related
I have been trying to use neography for the following basic use case, but can't seem to get it to work:
For a given node, tell me all the associated relationships for that node.
For a given node and a specific relationship, return the node or nodes in that relationships?
I followed the examples from here: https://maxdemarzi.com/2012/01/04/getting-started-with-ruby-and-neo4j/
I tried the following code:
def create_person(name)
Neography::Node.create("name" => name)
end
johnathan = create_person('Johnathan')
mark = create_person('Mark')
phil = create_person('Phil')
mary = create_person('Mary')
luke = create_person('Luke')
johnathan.both(:friends) << mark
First, I want to see the associated relationships that are incoming. My expectation is to see relationship with type :friends:
johnathan.incoming
=> #<Neography::NodeTraverser:0x0000000133f1c0 #from=#<Neography::Node name="Johnathan">, #order="depth first", #uniqueness="none", #relationships=[{"type"=>"", "direction"=>"in"}]>
I tried relationships:
2.2.1 :060 > johnathan.incoming.relationships
=> [{"type"=>"", "direction"=>"in"}]
My expectation would be to see "type"=>":friends" but I don't.
However, when I try the following, I do, but it doesn't work for my use case since I want to know what the relationships are without knowing in advance what they are:
2.2.1 :061 > johnathan.incoming(:friends).relationships
=> [{"type"=>"friends", "direction"=>"in"}]
Second use case is to actually retrieve the nodes, which does work.
Question:
How can I get the types of relationships associated for any given node?
I think I am close to figuring it out:
johnathan.rels.map{|n| n}.first.rel_type
=> "friends"
You are right, almost there. The documentation for this is at the bottom of https://github.com/maxdemarzi/neography/wiki/Phase-2-Node-relationships#retrieval-by-type but basically:
n1 = johnathan
n1.rels # Get node relationships
n1.rels(:friends) # Get friends relationships
n1.rels(:friends).outgoing # Get outgoing friends relationships
n1.rels(:friends).incoming # Get incoming friends relationships
n1.rels(:friends, :work) # Get friends and work relationships
n1.rels(:friends, :work).outgoing # Get outgoing friends and work relationships
There is no way to get just what are all the relationship types connected to me as far as I know, but that would be a good improvement in the Neo4j REST API.
The functionality exists in the Java API, see https://neo4j.com/docs/java-reference/current/javadocs/org/neo4j/graphdb/Node.html#getRelationshipTypes--
This is my first attempt at Neo4j, please excuse me if I am missing something very trivial.
Here is my problem:
Consider the graph as created in the following Neo4j console example:
http://console.neo4j.org/?id=y13kbv
We have following nodes in this example:
(Person {memberId, memberName, membershipDate})
(Email {value, badFlag})
(AccountNumber {value, badFlag})
We could potentially have more nodes capturing features related to a Person like creditCard, billAddress, shipAddress, etc.
All of these nodes will be the same as Email and AccountNumber nodes:
(creditCard {value, badFlag}), (billAddress {value, badFlag}),etc.
With the graph populated as seen in the Neo4j console example, assume that we add one more Person to the graph as follows:
(p7:Person {memberId:'18' , memberName:'John', membershipDate:'12/2/2015'}),
(email6:Email {value: 'john#gmail.com', badFlag:'false'}),
(a2)-[b13:BELONGS_TO]->(p7),
(email6)-[b14:BELONGS_TO]->(p7)
When we add this new person to the system, the use case is that we have to check if there exists a path from features of the new Person ("email6" and "a2" nodes) to any other node in the system where the "badFlag=true", in this case node (a1 {value:1234, badFlag:true}).
Here, the resultant path would be (email6)-[BELONGS_TO]->(p7)<-[BELONGS_TO]-(a2)-[BELONGS_TO]->(p6)<-[BELONGS_TO]-(email5)-[BELONGS_TO]->(p5)<-[BELONGS_TO]-(a1:{badFlag:true})
I tried something like this:
MATCH (newEmail:Email{value:'john#gmail.com'})-[:BELONGS_TO]->(p7)-[*]-(badPerson)<-[:BELONGS_TO]-(badFeature{badFlag:'true'}) RETURN badPerson, badFeature;
which seems to work when there is only one level of chaining, but it doesn't work when the path could be longer like in the case of Neo4j console example.
I need help with the Cypher query that will help me solve this problem.
I will eventually be doing this operation using Neo4j's Java API using my application. What could be the right way to go about doing this using Java API?
You had a typo in you query. PART_OF should be BELONGS_TO. This should work for you:
MATCH (newEmail:Email {value:'john#gmail.com'})-[:BELONGS_TO]->(p7)-[*]-(badPerson)<-[:BELONGS_TO]-(badFeature {badFlag:'true'})
RETURN badPerson, badFeature;
Aside: You seem to use string values for all properties. I'd replace the string values 'true' and 'false' with the boolean values true and false. Likewise, values that are always numeric should just use integer or float values.
I'd like to make a cypher query that generates a specific json output. Part of this output includes an object with a dynamic amount of keys relative to the children of a parent node:
{
...
"parent_keystring" : {
child_node_one.name : child_node_one.foo
child_node_two.name : child_node_two.foo
child_node_three.name : child_node_three.foo
child_node_four.name : child_node_four.foo
child_node_five.name : child_node_five.foo
}
}
I've tried to create a cypher query but I do not believe I am close to achieving the desired output mentioned above:
MATCH (n)-[relone:SPECIFIC_RELATIONSHIP]->(child_node)
WHERE n.id='839930493049039430'
RETURN n.id AS id,
n.name AS name,
labels(n)[0] AS type,
{
COLLECT({
child.name : children.foo
}) AS rel_two_representation
} AS parent_keystring
I had planned for children.foo to be a count of how many occurrences of each particular relationship/child of the parent. Is there a way to make use of the reduce function? Where a report would generate based on analyzing the array proposed below? ie report would be a json object where each key is a distinct RELATIONSHIP and the property value would be the amount of times that relationship stems from the parent node?
Thank you greatly in advance for guidance you can offer.
I'm not sure that Cypher will let you use a variable to determine an object's key. Would using an Array work for you?
COLLECT([child.name, children.foo]) AS rel_two_representation
I think, Neo4j Server API output by itself should be considered as any database output (like MySQL). Even if it is possible to achieve, with default functionality, desired output - it is not natural way for database.
Probably you should look into creating your own server plugin. This allows you to implement any custom logic, with desired output.
I need to create a python function such that it adds nodes and relationship to a graph and returns the number of created nodes and relationships.
I have added the nodes and relationship using graph.cypher.execute().
arr_len = len(dic_st[story_id]['PER'])
for j in dic_st[story_id]['PER']:
graph.cypher.execute("MERGE (n:PER {name:{name}})",name = j[0].upper()) #creating the nodes of PER in the story
print j[0]
for j in range(0,arr_len):
for k in range(j+1,arr_len):
graph.cypher.execute("MATCH (p1:PER {name:{name1}}), (p2:PER {name:{name2}}) WHERE upper(p1.name)<>upper(p2.name) CREATE UNIQUE (p1)-[r:in_same_doc {st_id:{st_id}}]-(p2)", name1=dic_st[story_id]['PER'][j][0].upper(),name2=dic_st[story_id]['PER'][k][0].upper(),st_id=story_id) #linking the edges for PER nodes
What I need is to return the number of new nodes and relationships created.
What I get to know from the neo4j documentation is that there is something called "ON CREATE" and "ON MATCH" for MERGE in cypher, but thats not being very useful.
The browser interface for neo4j do actually shows the number of nodes and relationship updated. This is what I need to return, but I am not getting quite the way for it to access it.
Any help please.
In case you need the exact counts of properties either created or updated then you have use "Match" with "Create" or "Match" with "Set" and then count the size of results. Merge may not return which ones are updated and which ones are created.
When you post your query against the Cypher endpoint of the neo4j REST API without using py2neo, you can include the argument "includeStats": true in your post request to get the node/relationship statistics. See this question for an example.
As far as I can tell, py2neo currently does not support additional parameters for the Cypher query (even though it is using the same API endpoints under the hood).
In Python, you could do something like this (using the requests and json packages):
import requests
import json
payload = {
"statements": [{
"statement": "CREATE (t:Test) RETURN t",
"includeStats": True
}]
}
r = requests.post('http://your_server_host:7474/db/data/transaction/commit',
data=json.dumps(payload))
print(r.text)
The response will include statistics about the number of nodes created etc.
{
"stats":{
"contains_updates":true,
"nodes_created":1,
"nodes_deleted":0,
"properties_set":1,
"relationships_created":0,
"relationship_deleted":0,
"labels_added":1,
"labels_removed":0,
"indexes_added":0,
"indexes_removed":0,
"constraints_added":0,
"constraints_removed":0
}
}
After executing your query using x = session.run(...) you can use x.summary.counters to get the statistics noted in Martin Perusse's answer. See the documentation here.
In older versions the counters are available as a "private" field under x._summary.counters.
This question is similar to this: create relationships between nodes in parallel and this Neo4j: Best way to batch relate nodes using Cypher?
I would like to parameterize a batch for creating relationships using a Cypher query and Neo4jClient (a c# client for Neo4j).
How would I write this out (specifically focusing on performance) - i.e. using only match and create statements and not Merge as merge ends up timing out for some reason?
I was thinking I could do something like this ( as stated in that second SO link)
MATCH (s:ContactPlayer {ContactPrefixTypeId:{cptid}})
MATCH (c:ContactPrefixType {ContactPrefixTypeId:{cptid}})
CREATE c-[:CONTACT_PLAYER]->s
with params:
{
"query":...,
"params": {
"cptid":id1
}
}
But this doesn't work, because it's trying to match the property as an Array.
I modified it to use WHERE x.Y IN {params} but this was extremely slow. The second recommendation was to try to use the transactional endpoint for Neo4j but I'm unsure how to do that with Neo4jClient.
This was the recommendation from the 2nd SO link above:
{
"statements":[
"statement":...,
"parameters": {
"cptid":id1
},
"statement":...,
"parameters": {
"cptid":id2
}
]
}
I did see this pull request but did not see that it had been implemented yet: https://github.com/Readify/Neo4jClient/pull/26
Without transaction support, is there another way to do this?
What's the performance when you use the query below?
USING PERIODIC COMMIT 1000
MATCH (s:ContactPlayer), (c:ContactPrefixType)
WHERE s.ContactPrefixTypeId = c.ContactPrefixTypeId
CREATE c-[:CONTACT_PLAYER]->s
If you want to try out the periodic commit statement, you'll have to use version 2.1.0-M1 for now. Otherwise, you can leave it out.