Searching nodes and properties of nodes - neo4j

I am trying to create a search function for my meetup app which uses Neo4j as the database. Is there a way to search both nodes (Topic, Department, and Title, getting the people that are attached to them) and properties of nodes (first name, last name, username, bio).
The Person node has a relationship to a Title node (via IS_TITLED) and a relationship to Department node (via EMPLOYED_BY) and relationship to Topic nodes (via INTEREST_OF or SKILL_OF)
Also I would like to make sure that the results are distinct for each person so if the person puts in the title of a person and a department and it gets 2 matches, then the person only returns once.

Your question is very broad, but here is an example query that:
Finds all people employed by the Finance department and have the titled "Clerk".
Ensures they are distinct people.
Returns their first name, last name, username, and bio.
MATCH (d:Department)<-[:EMPLOYED_BY]-(p:Person)-[:IS_TITLED]->(t:Title)
WHERE d.name = "Finance" AND t.name = "Clerk"
WITH DISTINCT p
RETURN p.fname AS firstname, p.lname AS lastname, p.username AS username, p.bio AS bio;

Actually I wasn't looking for an entire application. My final solution was to add,update, and remove documents in ElasticSearch when my nodes where added, update, and removed. Then I use ElasticSearch to find results and return a list of node id's. Then I wrote my Cypher query to pull information using IN for the returned id's to produce the results. It seems to work perfectly. Since I couldn't find an integrated solution for syncing Neo4j and ElasticSearch, I use both libraries in my application and just perform the appropriate action on ElasticSearch when the nodes were effected.

Related

Combining related information within a cypher query

I have created a knowledge with the nodes and relationships pictured. Each person has any number of jobs and skills connected to them and each Job and Skill can have any number of People connected to them. I would like to be able to search for a particular job (e.g. Security Architect) and return a list of all the people who have been employed_as that job and all of the skills that each person is skilled_in. I have created a query hich retrieves these results, however a new line in the query is created for each skill, duplicating the person details each time. This is the query I have which retrieves those results.
MATCH (j:Job {job_title: "Security Architect"})<-[p_rel:employed_as]-(p:Person)-[skilled_in]->(s:Skill) return p,s,p_rel
Is it possible to create a query that returns all of the skill nodes connected to a person as a single list with the details of that person?
Since you need all skills in single line, you can collect all the skills per person.
MATCH (j:Job {job_title: "Security Architect"})<-[p_rel:employed_as]-(p:Person)
-[skilled_in]->(s:Skill)
RETURN p,p_rel, collect(s) as skills_per_person

How to show (graphically) transitive relationships in neo4j without altering the data

Let's say my data include nodes of the type Person, Company and Country.
A person WORKS_AT a company and a company IS_IN a country.
CREATE (Person {name:"Paul"});
CREATE (Company {brand:"BG"});
CREATE (Country {code:"UK"});
MATCH (person {name:"Paul"}),(company {brand:"BG"}) CREATE (person)-[worksat:WORKS_AT]->(company) return person,worksat,company
MATCH (company {brand:"BG"}),(country {code:"UK"}) CREATE (company)-[isin:IS_IN]->(country) return company,isin,country
So what i want is to be able to see the person->country data in a visual graph way, in the neo4j default browser, bypassing completely the company node in between (which should not be visible).
But without creating a direct permanent relationship between the Person node and the Country node.
Thanks in advance.
You can use virtual relationships in the graphical result using APOC Procedures (these are not saved to your graph data).
Here's how this would work, provided that the nodes are labeled accordingly (your above creation queries aren't adding labels, so definitely fix that):
MATCH (p:Person)-[:WORKS_AT]->()-[:IS_IN]->(c:Country)
CALL apoc.create.vRelationship(p,'WORKS_IN',{},c) yield rel
RETURN p, rel, c

Neo4J query to find same data link to different nodes

Following is what I created in Neo4j:
Nodes: Customer Names, Customer Address and Customer Contact
Linked these nodes based on common relationships between all three.
I can see all three nodes linked in Neo4j. Contact contain email and phone numbers so some cases customer name node is connected to email address, phone number and address.
In my learning curve I am asked to show how many same contacts are used by different customer names also how many same address used by different customer names. Based on my little experience I tried few queries but couldnt reach to results.
Tried following query -
start n=node(*)
match n-[:CONTACT_AT]-()
return distinct n
CONTACT_AT is the relationship between customer name and Contact (email, phone) node.
Your question does not provide enough information about your data model. To save time, I will assume that it looks something like this (without showing all the properties):
(a:Address)<-[:ADDRESS_AT]-(p:Person {name: '...'})-[:CONTACT_AT]->(c:Contact)
With this model, this is how you'd get all the names of the people who have the same Contact:
MATCH (person:Person)-[:CONTACT_AT]->(contact:Contact)
RETURN contact, COLLECT(person.name) AS names;
And this is how you'd get all the names of the people who have the same Address:
MATCH (person:Person)-[:ADDRESS_AT]->(address:Address)
RETURN address, COLLECT(person.name) AS names;

Is there any tool for showing relationships between two entities

I'm looking for a tool that could fit to the next task.
For example, user selects in interface entity University and types in some id-s for searching it and gets the result of universities list related to his request, then he does the same with entity Person and at last he types the maximum relationship length. The result of his request is some graph of relationships for example.
(: Person) -[: IS_BROTHER] ->(: Person) -[: IS_STUDENT] ->(: University)
or he might get several results that fits relationship length
I'm not very experienced with neo4j and don't know if there is any tool to fit this task. Or any other tool not related to neo4j would be fine, but I doubt that sql works fine with relationship search. Thanks.
Edited
I'm loking for user friendly tool that will generate this request without user knowing chypher language at all
Here is a Cypher query that returns all paths that are at most 5 relationships deep between any Person whose ID is in a given list and any University whose ID is in another list:
MATCH path=(p:Person)-[*..5]->(u:University)
WHERE ID(p) IN [1,22,333] AND ID(u) IN [2,444,192,678]
RETURN path;
You could use the neo4j Browser to see the paths.

Neo4j Relationship Schema Indexes

Using Neo4j 2.1.4 and SDN 3.2.0.RELEASE
I have a graph that connects nodes with relationships that have a UUID associated with them. External systems use the UUID as a means to identify the source and target of the relationship. Within Spring Data Neo4j (SDN) we have a #RelationshipEntity(type=”LINKED_TO”) class with a #StartNode, #EndNode and a String uuid field. The uuid field is #Indexed and the resulting schema definition in Neo4j shows up as
neo4j-sh (?)$ SCHEMA
==> Indexes
...
==> ON :Link(uuid) ONLINE
...
However, running a cypher query against the data, e.g.
MATCH ()-[r:LINKED_TO]->() WHERE uuid=’XXXXXX’ RETURN r;
does a full scan of the database and takes a long time
If I try to use the index by running
MATCH ()-[r:LINKED_TO]->() USING INDEX r:Link(uuid) WHERE uuid=’XXXXXX’ RETURN r;
I get
SyntaxException: Type mismatch: expected Node but was Relationship.
As I understand it, Relationships are supposed to be first class citizens in Neo4j, but I can’t see how to utilize the index on the relationship to prevent the graph equivalent of a table scan on the database to locate the relationship.
I know there are posts like How to use relationship index in Cypher which ask similar things, but this Link is the relationship between the two nodes. If I converted the Link to a Node, we would be creating a Node to represent a Relationship which seems wrong when we are working in a graph database - I'd end up with ()-[:xxx]->(:Link)-[:xxx]->() to represent one relationship. It would make the model messy purely due to the fact that the Link couldn't be represented as a relationship.
The Link has got a unique, shared key attached to it that I want to use. The Schema output suggests that the index is there for that field - I just can't use it.
Does anyone have any suggestions?
Many thanks,
Dave
Schema indexes are only available for nodes. The only way to index relationships is using legacy indexes or autoindexes. Legacy indexes need to be used explicitly in the START clause:
START r=relationship:my_index_name(uuid=<myuuid>)
RETURN r
I'm not sure how this can be used in conjunction with SDN.
side note: requiring relationship index is almost always a indication of doing something wrong in your graph data model. Everything being a thing or having an identity in your domain should be a node. So if a relationship requires a uuid, maybe the relationship refers to a thing and therefore should be converted into a node having a inbound relationship to the previous start node and a outbound relationship to the previous end node.

Resources