Neo4j OGM | Adhoc Cypher Queries - neo4j

I'm trying to run adhoc cyphers (where the results don't necessarily always map to the domain entity object).
I'm using the
session.query(cypher)
API for that.
Not sure what should be the output type?
An example is:
I've got Event, Flight modelled as first class entities and they are related via "HAS_FLIGHT"
I run this Cypher Query:
session.query("MATCH (p:Event)-[hf:HAS_FLIGHT]->(f:Flight)
RETURN p,hf,f,count(p) AS totalEvents")
Interestingly I only get returned an arraylist of the value counts (ie the totalEvents).
How can I get all the values mentioned in the RETURN clause in a map or something and I can build the domain objects after the retrieval.

There is no need to return a map if you just want to construct your domain objects from a query.
session.query("MATCH p=(:Event)-[:HAS_FLIGHT]->(:Flight) return nodes(p), rels(p)")
This will return an Iterable of all events having one or more flights.

Which session do you use? When I'm looking at org.neo4j.ogm.session.Session I can only see query overloads with more than one argument.
Two of them return a org.neo4j.ogm.model.Result object that contains a map for each result row. The map holds the value for each of the items in the return clause.

Related

Create relationship with properties using a query in Cypher

I would like to know if this is possible. I have a query that produces a nice report showing a relationship between two entities through two other nodes. There can be more than one path. I now want to create a direct relationship between those two nodes and count the number of paths and sum based upon data in the nodes in between. the report query is below.
match (bo:BuyerAgency)<-[:IS_FOR_BO]-(sol:Solicitation)-[:SELECTED]->(prop:Proposal)<-[:OWNS_BID]-(so:VendorOrg)
where sol.currStatus='Awarded'
return bo.AgencyName, count(sol.Number) as awards, so.orgName, sum(prop.finalPrice) as awardVolume;
What I want to do is similar to below which will not work.
match (bo:BuyerAgency)<-[:IS_FOR_BO]-(sol:Solicitation)-[:SELECTED]->(prop:Proposal)<-[:OWNS_BID]-(so:VendorOrg)
where sol.currStatus='Awarded'
create (bo)-[:HAS_AWARDED{awardCount: count(sol.Number), awardVolume: sum(prop.finalPrice)}]->(so);
If I remove the properties for the relationship, it works but want to add the properties without to much programing.
I am using the most recent version of Neo4j 3.2.
thanks
The problem here is you are trying to use count() and sum() functions in an invalid context. The below query should work:
match (bo:BuyerAgency)<-[:IS_FOR_BO]-(sol:Solicitation)-[:SELECTED]->(prop:Proposal)<-[:OWNS_BID]-(so:VendorOrg)
where sol.currStatus='Awarded'
with bo, so, count(sol.Number) as count_sol, sum(prop.finalPrice) as sum_finalPrice
create (bo)-[:HAS_AWARDED{awardCount: count_sol, awardVolume: sum_finalPrice}]->(so);
This query uses WITH to pass bo, so and the result of the aggregation functions count(sol.Number) and sum(prop.finalPrice) to the next context. After, these values are used to create the new relation between bo and so.

Depth in custom Cypher queries with OGM always 0?

I'm currently evaluating OGM / Spring Data Neo4j for a use case and came upon the following problem:
When executing a custom Cypher query either via Spring Data #Query annotation or directly via the Neo4j Session, the result contains only the nodes directly queried for and not the related nodes (relationships are null in the resulting node objects). I.e. the depth for these queries seems to be 0 and not 1, as I would have expected from the docs.
How can I execute a custom Cypher query via OGM or Spring Data Neo4j that has depth 1?
The default depth 1 refers to findOne/findAll/.. methods from the repository and derived finders.
This is what the documentation says about custom queries:
In the current version, custom queries do not support paging, sorting or a custom depth. In addition, it does not support mapping a path to domain entities, as such, a path should not be returned from a Cypher query. Instead, return nodes and relationships to have them mapped to domain entities.
http://docs.spring.io/spring-data/data-neo4j/docs/current/reference/html/#reference:session:loading-entities:cypher-queries
For example when you have a query
MATCH (n:MyLabel)-[r]-(n2)
WHERE ... // some condition
RETURN n,r,n2
list all nodes/relationships you want to map to your objects in the RETURN clause.

How can I filter relationship condition for multiple iteration specified with Cypher?

I would like to get all nodes and relationships matching certain condition in relationship.
MATCH(a:DB {TABLE:'CONT',COLUMN:'STATUS_CDE'})-[b:RELATED*..]->(c:DB)
WHERE b.CLAUSE IN ['where','join','unknown']
RETURN a,b,c
But I got the below error message, when I tried to execute the above query.
Type mismatch: expected Map, Node or Relationship but was Collection<Relationship>
I am using Neo4j community edition v3.0.1.
How can I achieve my goal?
This is because you use a variable depth for relationship type RELATED - b is now a collection of relationships, not a single relation upon which you can use the IN operator.
Depending on whether you want every relationship to have one of these values, or just some/one, you can use one of the predicate functions like this
MATCH(a:DB {TABLE:'CONT',COLUMN:'STATUS_CDE'})-[b:RELATED*..]->(c:DB)
WHERE all(rel in b where rel.name in ['where','join','unknown'])
RETURN a,b,c
(untested)

Recommended way of getting single relationship of specific type between two nodes

Although title is clear,
I need to remove a relationship between two nodes of a specific relationship type.
Neither getSingleRelationship function of Node nor overloaded versions of getRelationships have second node parameter.
Should I get all relationships and iterate over it to find relationship? Is there any constant time way?
What is the recommended way in Core API or Traversal API?
Why don't you use a Cypher query? The library has this possibility. Just use the cypher query function (see their doc for the exact name, I don't remember) and then use this query:
START n=node(_id1), m=node(_id2) MATCH n-[rel:RELATIONSHIP_TYPE]-m RETURN DISTINCT rel;
where _id1 and _id2 are the internal ids of the nodes in Neo4J
If you use Neo4J 2.0 (highly recommended), your query would look something like:
MATCH (n{id:"_id1"}), (m{id:"_id2"}), n-[rel:RELATIONSHIP_TYPE]-m RETURN DISTINCT rel;
in that latter case you could actually use any property in the place of id - for example, your own unique id for the node, or their names, etc.
In the end Neo4J is explicitly saying they're moving away from REST API towards Cypher, so it makes sense to use Cypher where possible and it's also more precise what you get like that.
Yes you would iterate over the relationships and check the end-node:
public Relationship getRelationshipBetween(Node start, Node end, Direction direction, RelationshipType type) {
for (Relationship r: start.getRelationships(direction,type)) {
if (r.getOtherNode(start).equals(end)) return r;
}
return null;
}

Combining two neo4j cypher calls into one call

I have the following two cypher calls that I'd like to combine into one;
start r=relationship:link("key:\"foo\" and value:\"bar\"") return r.guid
This returns a relationship that contains a guid that I need based on a key value pair (in this case key:foo and value:bar).
Lets assume r.guid above returns 12345.
I then need all the property relationships for the object in question based on the returned guid and a property type key;
start r=relationship:properties("to:\"12345\" and key:\"baz\"") return r
This returns several relationships which have the values I need, in this case all property types baz that belong to guid 12345.
How do I combine these two calls into one? I'm sure its simple but I'm stumbling..
The answer I've gotten is that there is no way to perform an index lookup in the middle of a Cypher query, or to use a variable you have declared to perform the lookup.
Perhaps in later version of Cypher, as this ability should be standard especially with the dense node issue and the suggested solution of indexing.

Resources