I need to find all nodes connected with relation that has attribute fld = email. Neo4j Cypher complains the following as a query with bad syntax:
MATCH (n)-[r:rel*..]-(m) WHERE has(r.fld) and r.fld='email' RETURN n,r,m
What would be the right one?
Best bet:
MATCH (n)-[r:rel {fld: 'email'}]-(m) RETURN n, r, m;
This should match nodes that are connected with a "rel" relationship that has a property "fld" with the value "email".
HTH
Related
I am new to Neo4j DB and I have a Neo4j DB with the following nodes,
Attribute
Entity1
Entity2 - has relation with children as label CHILD
Entity2-1
Entity2-2
...
Entity2-n
And all entities may have relation with others which has label VALUE and property value.
Relationships:
Entity2 -> Attribute
Entity2-n -> Attribute
Entity2 -> Entity1
Entity2-n -> Entity1
Entity1 -> Attribute
I need to fetch these node's relation values and if entity has no direct value then need to fetch it's parent entity value.
For example, if entity2-2has no relation with Attribute, then need to check if it's parent entity2 has relation with value, if not get the Attribute node value.
For this, I am trying this query, but not working as expected and getting empty values
MATCH (a:ATTRIBUTE {name: 'test' })
match (e1:ENTITY1 {id:'c0f333ca-a9cc-4c09-ac30-7c460512f1f9' })
optional match ((e1)-[entity1GlobalValue:VALUE {id:a.id}]->(a))
optional match ((e2:ENTITY2 {id: 'c47004cc-3f48-51fd-9a38-69274341e344'})-[:CHILD]->(e2Children:ENTITY2))
optional match ((e2Children)<-[:CHILD*]-(e2Parent:ENTITY2))
optional match ((e2Children)<-[e2ChildrenE1Values:VALUE {id:a.id}]-(e1))
optional match ((e2Parent)<-[e2ParentE1Values:VALUE {id:a.id}]-(e1))
optional match ((e2Children)<-[e2ChildrenGlobalValues:VALUE {id:a.id}]-(a))
optional match ((e2Parent)<-[e2ParentGlobalValues:VALUE {id:a.id}]-(a))
RETURN a, e1, entity1GlobalValue, e2Children, e2ChildrenE1Values, e2ParentE1Values, e2ChildrenGlobalValues, e2ParentGlobalValues;
Not sure what is the mistake here?
Is my query effiecent ? There is Unique constraint on id field.
Update:
Rough diagram:
Here I am looking for value which is stored in the relations between Nodes.
Entity2 has children Entity2-1 and Entity2-2, where I have to find the value for these children with other entities - Entity1 and Attribute.
Thanks
Based on the graph provided I understand that you have to get the values for the child nodes which has relationship VALUE. If that's the case find the below query.
MATCH (n:Entity2)-[:CHILD]->(c)
with collect(c)+n as childNodes
UNWIND childNodes as cNode
MATCH (cNode)-[v:VALUE]->(endNode)
RETURN
labels(cNode) as fromNode,
v.value as value,
labels(endNode) as toNode
The result would be
What I have done is assuming the starting Node as parent Node I have collected all the child nodes plus the parentNode and using unwind looping each node collected and checking whether it has VALUE relationship and if so returning the values.
Hope this helps!
If not let me know what's the result you are expecting.
Thanks!
Been stuck for days with this concern, trying to accomplish this:
See the provided picture.
The black is the start vertex. Trying to get:
1: All child parts OUTBOUND (from) the start vertex
2: Condition: The children MUST have the INBOUND edge"types" and the other end a document with a variable set to "true" and of the type "type".
3: When a document of type "part" fails to met up the requirements with INBOUND document of type "type" with a attribute to "true", it stops the expand for that path then and there.
4: The documents who failed isn't included in the result either.
5: Should be compatible with any depths.
6: No subqueries (if possible without).
Example of graph
With the given information, the data model seems questionable. Why are there true and false vertices instead of a boolean edge attribute per partScrew? Is there a reason why it is modeled like this?
Using this data model, I don't see how this would be possible without subqueries. The traversal down a path can be stopped early with PRUNE, but that does not support subqueries. That only leaves FILTER for post-filtering as option, but be careful, you need to check all vertices on the path and not just the emitted vertex whether it has an inbound false type.
Not sure if it works as expected in all cases, but here is what I came up with and the query result, which looks good to me:
LET startScrew = FIRST(FOR doc IN screw LIMIT 1 RETURN doc) // Screw A
FOR v,e,p IN 1..2 OUTBOUND startScrew partScrew
FILTER (
FOR v_id IN SHIFT(p.vertices[*]._id) // ignore start vertex
FOR v2 IN 1..1 INBOUND v_id types
RETURN v2.value
) NONE == false
RETURN {
path: CONCAT_SEPARATOR(" -- ", p.vertices[*].value)
}
path
Screw A -- Part D
Screw A -- Part E
Screw A -- Part E -- Part F
Dump with test data: https://gist.github.com/Simran-B/6bd9b154d1d1e2e74638caceff42c44f
I am new to Gremlin and have just started with it.I have a graph where every vertex has a property Referenceable.qualifiedName and __typeName.
Edge label between vertices with '__typeName' as 'avro_schema' and 'avro_field' is '__avro_record.fields' and there is 1 to many relationship between 'avro_schema'(1) and 'avro_field'(many).
Edge label between vertices with '__typeName' as 'avro_field' and 'DataClassification' is 'classifiedAs' and there is 1 to many relationship between 'avro_field'(1) and 'DataClassification'(many).
I want to find out all 'avro_schema' vertices property 'Referenceable.qualifiedName' in the graph where each of the 'avro_field' has a 'classifiedAs' relationship to 'DataClassification'
I have tried the gremlin query to find out given a particular avro_schema find out the number of avro_field which has a relationship to DataClassification via classifiedAs. That works.
But i am not able to keep a count of the edges between avro_schema to avro_field and then compare with number of avro_field which has relationship to DataClassification type.
This gives number of classified avro_field for a give avro_schema
g.V().has('__typeName','avro_schema').has('Referenceable.qualifiedName' , "com.example.avro.test2Complicated16").outE('__avro_record.fields').inV().out('classifiedAs').has('__typeName','tDataClassification').count()
Also I tried to this to aggregate across all avro_schema which satisfies the condition,but it doesn't work.
g.V().has('__typeName','avro_schema').where(identity().out('__avro_record.fields').store('sumi').out('classifiedAs').has('__typeName','DataClassification').count().is(eq('sumi'.size()))).values('Referenceable.qualifiedName')
I want to know all the avro_schema in which all the avro_field has any of the 'classifiedAs' edge relationship to DataClassification
On further trying I got down to the query but size of the collection 'xm' is always returned as 0.
g.V().has('__typeName','avro_schema').local(out('__avro_record.fields').store('xm').local(out('classifiedAs').has('__typeName', 'DataClassification').count().is(eq(1))).count().is(eq(select('xm').size())))
Not sure if I'm following the problem description correctly, but here's a wild guess for the traversal you might be looking for:
g.V().has('__typeName','avro_schema').not(
out('__avro_record.fields').
out('classifiedAs').has('__typeName',neq('DataClassification'))).
values('Referenceable.qualifiedName')
UPDATE
// at least one __avro_record.fields relation
g.V().has('__typeName','avro_schema').filter(
out('__avro_record.fields').
groupCount().
by(choose(out('classifiedAs').has('__typeName','DataClassification'),
constant('y'), constant('n'))).
and(select('y'), __.not(select('n')))).
values('Referenceable.qualifiedName')
// include avro_schema w/o __avro_record.fields relations
g.V().has('__typeName','avro_schema').not(
out('__avro_record.fields').
groupCount().
by(choose(out('classifiedAs').has('__typeName','DataClassification'),
constant('y'), constant('n'))).
select('n')).
values('Referenceable.qualifiedName')
I'm interested in using traversals to quickly find all the documents linked to an initial document. For this I'd use:
let id = 'documents/18787898'
for d in documents
filter d._id == id
for i in 1..1 any d edges
return i
This generally provides me with all the documents related to the initial ones. However, say that in these edges I have more information than just the standard _from and _to. Say it also contains order, in which I indicate the order in which something is to be displayed. Is there a way to also grab that information at the same time as making the traversal? Or do I now have to make a completely separate query for that information?
You are very close, but your graph traversal is slightly incorrect.
The way I read the documentation, it shows that you can return vertex, edge, and path objects in a traversal:
FOR vertex[, edge[, path]]
IN [min[..max]]
OUTBOUND|INBOUND|ANY startVertex
edgeCollection1, ..., edgeCollectionN
I suggest adding the edge variable e to your FOR statement, and you do not need to find document/vertex matches first (given than id is a single string), so the FOR/FILTER pair can be eliminated:
LET id = 'documents/18787898'
FOR v, e IN 1 ANY id edges
RETURN e
I am using ArangoDB 2.8
I am doing a traversal query that includes 2 different collections. However in my result I would like to get only a particular collection, but I don't see the way to filter by collection name.
In my case I have address collection and user collection. In address collection I distinguish 3 levels as: {addressType: state}, {addressType: city} and {addressType: street}. Then I have an edge that links from address to user collection (state>city>street>user). I want to do a traversal (like in the code below) from an address (of any type) to the user (if any) and only return the collection of type user -for example if a street does not have a link to a user then return empty-.
For p in TRAVERSAL(address, myEdge, #vertex_id, 'outbound', {paths:false})
RETURN p.vertex._id)
Another answer is using the IS_SAME_COLLECTION function as hinted by this SO answer:
FOR p IN TRAVERSAL(address, myEdge, #vertex_id, 'outbound', {paths:false})
FILTER IS_SAME_COLLECTION('user', p.vertex._id)
RETURN p.vertex._id)
or, since TRAVERSAL was removed in ArangoDB 3.0+ (see this answer and the migration guide), something like
FOR v IN 0..5 IN OUTBOUND #vertex_id myEdge
FILTER IS_SAME_COLLECTION('user', v._id)
RETURN v._id)
Well I had to find a solution, so here is mine (I know is not the best but worked for me):
What I do is split the _id by "/" and check whether the first part (collection name) is in ['user']
For p in TRAVERSAL(address, myEdge, #vertex_id, 'outbound', {paths:false})
FILTER (SPLIT(p.vertex._id, "/", 1)[0]) IN ['user']
RETURN p.vertex._id)