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!
Related
Consider a Core Data model with two Entities: TermDictionary and Term. The TermDictionary has a "name" property, and a one-to-many relationship called "terms" which points to a set of Term objects, each of which consists of two properties: "name" and "score".
I've got an NSFetchRequest which I'm using as a data source for a UITableView which displays all of the TermDictionaries in the database. The idea is that the table will, for each cell, display the name of the dictionary, along with a count of the number of terms in that dictionary.
In the following code snippet, item contains an NSFetchRequestResult for the "TermDictionary" entity:
let thisDict = item as! TermDictionary
cell.textLabel?.text = thisDict.name
cell.detailTextLabel?.text = "\(thisDict.terms?.count ?? 0) terms"
...The table cells are correctly displaying the names of the Term Dictionaries, however it looks like thisDict.terms is always coming up nil, so the number-of-terms label always shows zero.
Do I need do do something special with item rather than just casting it to my TermDictionary managed object subclass?
You do not need to do anything special. If thisDict.terms prints as nil, it really is nil. Check your data store.
I have imported a list of documents (in a collection named "assemblies"). One of the attributes is "parent_id".
Based on this, I want to construct the graph, that is implicitly described by this attribute.
"id","name","parent_id"
"30","Top level"
"30.1","30.1 Child 1","30"
"30.2","30.2 Child 2","30"
This is the query, that I expected to give me the info for creating the edge collection (named "contains", so it is from parent to child):
FOR assy IN assemblies
LET parent = (
FOR parent IN assemblies
FILTER parent.id == assy.parent_id
RETURN parent
)
RETURN {_from: parent._key, _to: assy._key}
What am I doing wrong? Could you give me the full query for inserting the edges?
The problem is that the result of your subquery in parent is an array and not an document. But there is actually no need of a subquery. You can also performe a join, which should offer better performance and is easier to read.
You also have to use the value of _id insteadt of _key for the fields _from and _to of your edges.
The following query does exactly what you want.
FOR assy IN assemblies
FOR parent IN assemblies
FILTER parent.id == assy.parent_id
INSERT {_from: parent._id, _to: assy._id} IN contains
RETURN NEW
Node: the RETURN NEW is optional. You can check with it whether the import was successful. With larger amount of data I would drop this.
Given a CouchDB view that emits keys of the following format:
[ "part1", { "property": "part2" } ]
How can you find all documents with a given value for part1?
If part2 was a simple string rather than an object startkey=["part1"]&endkey=["part1",{}] would work. The CouchDB docs state the following:
The query startkey=["foo"]&endkey=["foo",{}] will match most array keys with "foo" in the first element, such as ["foo","bar"] and ["foo",["bar","baz"]]. However it will not match ["foo",{"an":"object"}]
Unfortunately, the documentation doesn't offer any suggestion on how to deal with such keys.
The second element of your endkey value needs to be an object that collates after any possible value of the second element of your key. Objects are compared by property-by-property (for example, {"a":1} < {"a":2} < {"b":1}) so the best way to do this is to set the first property name in your endkey to a very large value:
startkey=["part1"]&endkey=["part1", { "\uFFF0": false }]
The property name of \uFFF0 should collate after any other property names in the second key element, and even works when the second element is an empty object or has more than one property.
I am trying to set a unique constraint for an edge collection so that only one edge of a certain type can be created between two given nodes. The issue is that it seems I can't use _from and _to attributes as path attributes when creating the index. What I have tried so far:
db._collection('edges').ensureUniqueConstraint('_from', '_to', 'type');
I get the following error:
[ArangoError 10: bad parameter]
I don't want to check whether a certain edge type between two nodes exists before creating it.
Any hints?
It is currently not possible to create secondary indexes on internal attributes such as _key, _id, _rev, _from, or _to. We want to allow this for a future version of ArangoDB, but it will be a massive code change.
The only way to achieve the desired result is to create an extra attribute in the edge that you save and put the combination of "_from", "_to", and "type" into it. I think these values should be known at edge creation already.
So instead of saving an edge like this
db.edges.save(_from, _to, { type: type, other: ... });
it should be like this:
// create a unique index on attribute "unique"
db._collection("edges").ensureUniqueConstraint("unique");
// create a variable "unique" which contains the values of _from and _to and type
var unique = _from + "-" + _to + "-" + String(type);
// now save the edge, using the "unique" attribute
db.edges.save(_from, _to, { type: type, unique: unique, other: ... });
This is a workaround, but it should solve that particular problem.
Since ArangoDB 3.0 you can ensure uniqueness of relations in edge collections with unique hash index on _from and _to fields.
db.edgeCollectionName.ensureIndex({ type: "hash", fields: [ "_from", "_to" ], unique: true });
When a A->B relation exists, another A->B won't be created. B->A can still be created, though.
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