Neo4j Query Not Returning Desired Output - database

Hi I am learning Neo4j Database, I had an issue with one of the query as it seems to be not returning a valid output. Here is my complete dataset
Query that giving issue is MATCH (usr:USER)-[:KNOWS]->(lang:SKILL) where lang.name="Python" AND lang.name="FastAPI" return usr,
Expected Output is Vibhav Node. But instead its not returning any value
Please help me to understand this. Thanks in Advance!!

You are setting two predicates on the same node, which will not work as a single node cannot have two names. What you need to do is:
MATCH (lang2:SKILL)<-[:KNOWS]-(usr:USER)-[:KNOWS]->(lang:SKILL)
where lang.name="Python" AND lang2.name="FastAPI"
return usr

From the visualization we can see that some urs have more than one lang skill. So, you could use OR logic and count the returns:
MATCH (usr:USER)-[r:KNOWS]->(lang:SKILL) where lang.name="Python" OR
lang2.name="FastAPI" with urs, count(*) as ct with usr where ct=2
return usr
This might run faster that Tomaz's suggestion ... you'll have to test it.This assumes you will not have duplicate edges to a skill node.

Related

How to get combined vertex results in gremlin using union/project/select?

below is my example graph
addV('user').property('userId','user2').as('u2').
addV('user').property('userId','user3').as('u3').
addV('group').property('groupId','group1').as('g1').
addV('group').property('groupId','group2').as('g2').
addV('group').property('groupId','group3').as('g3').
addV('folder').property('folderId','folder1').property('folderName','director').as('f1').
addV('folder').property('folderId','folder2').property('folderName','asstDirector').as('f2').
addV('folder').property('folderId','folder3').property('folderName','editor').as('f3').
addV('file').property('fileId','file1').property('fileName','scene1').
addE('in_folder').to('f3').
addE('in_folder').from('f2').to('f1').
addE('in_folder').from('f3').to('f2').
addE('member_of').from('u1').to('g1').
addE('member_of').from('u2').to('g2').
addE('member_of').from('u3').to('g3').
addE('member_of').from('g3').to('g1').
addE('has_permission').property('prm','view').from('g1').to('f1').
addE('has_permission').property('prm','view').from('g2').to('f2').
addE('has_permission').property('prm','view').from('g3').to('f3').
addE('has_permission').property('prm','view').from('u2').to('f1').iterate()
The use-case : Get both folders and files vertex as result where user3 have access to
im able to get either folder or files where user have access to, but not able to combine them.
below is the query which cam close but not exactly exptected resultset.
g.V().has('user','userId','user3').emit().until(__.not(outE('member_of'))).repeat(out('member_of'))
.outE('has_permission').has('prm','view').inV().as('f').inE('in').outV().as('a').select('a','f')
which results
==>[a:v[6144475224],f:v[164175920]]
==>[a:v[5202170056],f:v[204857480]]
the expectation is to get 3 vertexes with value Map, not just node ids.
f:v[164175920]
a:v[6144475224]
a:v[5202170056]
Could some one check and let me know how i can utilize union here.
tried below query
g.V().has('user','userId','user3').emit().until(__.not(outE('member_of'))).repeat(out('member_of'))
.outE('has_permission').has('prm','view').inV().inE('in').outV().map(union(valueMap())
this gives the file information only not the folder values.
You got it right in your comment query, only with few spelling mistakes which caused the error:
g.V().has('user','userId','user3').emit().repeat(out('member_of'))
.outE('has_permission').has('prm','view').inV().dedup()
.union(identity(),__.repeat(__.in('in_folder')).emit()).dedup()
This can be optimized a bit by moving the emit before the repeat and dropping the union:
g.V().has('user','userId','user3').emit().repeat(out('member_of'))
.outE('has_permission').has('prm','view').inV().dedup()
.emit().repeat(__.in('in_folder')).dedup()
Note that I used 'in_folder' instead on 'in' to match your sample data.

SQL Select on Records that Meet Criteria from Another Table

I've got a very complex query and trying to give a simple example of one of the sub-tables I'm having problems with, if you need more information or context please let me know.
I've posed a CSV file with some sample data here:
https://drive.google.com/open?id=0B4xdnV0LFZI1dzE5S29QSFhQSmM
We make cakes, and 99% of our cakes are made by us. The 1% is when we have a cake delivered to us from a subcontractor and we 'Receive' and 'Audit' it.
What I wanted to do was to write something like this:
SELECT
Cake.Cake
Instruction.Cake_Instruction_Key
Steps
FROM
Cake
Join Instruction
ON Cake.Cake_Key = Instruction.Cake_Key
JOIN Steps
ON Instruction.Step_Key = Steps.Step_Key
WHERE
MIN(Steps.Step_Key) = 1
This fails because you can't have an aggregate in the WHERE clause.
The desired results would be:
Cake C 13 Receive
Cake C 14 Audit
Cake D 15 Receive
Cake D 16 Audit
Thank you in advance for your help!
Take a look at the HAVING keyword:
https://msdn.microsoft.com/en-us/library/ms180199.aspx
It works more or less the same as the WHERE clause but for aggregate functions after the GROUP BY clause.
Beware however this can be slow. You should try filtering down the number of records as much as possible in the WHERE and even consider using a tempory table to aggregate the data into first.
What you're talking about is the GROUP BY/HAVING clause, so in your case you would need to add something like
GROUP BY Cake.Cake, Instruction.Cake_Instruction_Key, Steps
HAVING MIN(Steps.Step_Key) = 1

Cypher returns exponential count result on 'join'

I am learning Cypher on Neo4j and I am having trouble in understanding how to perform an efficient 'join' equivalent in Cypher.
I am using the standard Matrix character example and I have added some nodes to the mix called 'Gun' with a relation of ':GIVEN_TO'. You can see the console with my query result here:
http://console.neo4j.org/r/rog2hv
The query I am using is:
MATCH (Neo:Crew { name: 'Neo' })-[:KNOWS*..]->(other:Crew),(other)<-[:GIVEN_TO]-(g:Gun),(Neo)<-[:GIVEN_TO]-(g2:Gun)
RETURN count(g2);
I have given Neo 4 guns, but when I perform the above I get a count of '12'. This seems to be the case because there are 3 'others' and 3*4 = 12. So I get some exponential result.
What should my query look like to get the correct count ('4') from the example?
Edit:
The reason I am not querying through Guns directly as suggested by #ceej is because in my real use case I have to do this traversal as described above. Adding DISTINCT does not do anything for my result.
The reason you get 12 guns instead of 4 is because your query produces a cartesian product. This is because you have asked for items in the same match statement without joining them. #ceej rightly pointed out if you want to find Neo's guns you would do as he suggested in his first query.
If you wanted to get a list of the crew members and their guns then you could do something like this...
MATCH (crew:Crew)<-[:GIVEN_TO]-(g:Gun)
RETURN crew.name, collect(g.name)
Which finds all of the crew members with guns and returns their name and the guns that they were given.
If you wanted to invert it and get a list of the guns and the respective crew members they were give to you could do the following...
MATCH (crew:Crew)<-[:GIVEN_TO]-(g:Gun)
RETURN g.name, collect(crew.name)
If you wanted to find all of the crew that knew Neo multiple levels deep that were given a gun you could write the query like this...
MATCH (crew:Crew)<-[:GIVEN_TO]-(g:Gun)
WITH crew, g
MATCH (neo:Crew {name: 'Neo'})-[:KNOWS*0..]->(crew)
RETURN crew.name, collect(g.name)
That finds all the crew that were given guns and then determines which of them have a :KNOWS path to Neo.
Forgive me, but I am am unclear why you have the initial MATCH in your query. From your explanation it would appear that you are trying to get the number of :Gun nodes linked to Neo by the :GIVEN_TO relationship. In which case all you need is the latter part of your query. Which would give you something like
MATCH (neo:Crew { name: 'Neo' })<-[:GIVEN_TO]-(g:Gun)
RETURN count(g)
Furthermore, to make sure that you are only counting distinct :Gun nodes you can add DISTINCT to the RETURN statement.
MATCH (neo:Crew { name: 'Neo' })<-[:GIVEN_TO]-(g:Gun)
RETURN count( DISTINCT g )
This is possibly unnecessary in your case but can be helpful when the pattern that you are matching on can arrive at the same node by different traversals.
Have I misunderstood your requirement?

neo4j / cypher - why is starting node excluded?

I have a simple graph:
When I run this simple query in neoeclipse:
START me=node:node_auto_index(name="Me")
MATCH me-[:LIVES_IN]->()<-[:LIVES_IN]-(f)
RETURN f.name;
only my Girlfriend is returned!
Why am I excluded from the result?
Results
f.name Girlfriend
Because a path (what you specify in the match) will never contain the same relationship twice.
To find all the people living in the same location including yourself, you need to split into two actions, one finding your city and the other collecting people in this city using the with statement:
start me=node:node_auto_index(name='Me')
match me-[:LIVES_IN]->homebase
with homebase
match homebase<-[:LIVES_IN]-people
return people
See http://console.neo4j.org/?id=t0wjhg

SOLR (3.1+) - Multiple Spatial Queries with OR in Same Request

Is it possible to conduct multiple spatial queries within the same SOLR (3.1+) request?
We currently have a need to allow user to search for inventory with a location of their choice via a frontend search form. But we want to also add another spatial search behind the scenes so it will include more inventory. The resulting search would result in a venn diagram type of search.
Edit 10.4.2011
Example construct: q=*:*&fq={!geofilt}&sfield=Location&(ClientId:"client1"&pt=40.68063802521456,-74.00390625&d=80.4672)%20OR%20_query_:(ClientId:"client2"&pt=36.1146460,-115.1728160&d=80.4672)
The above construct does not work, but hopefully demonstrates what I am trying to accomplish.
This is old, but it doesn't seem like it ever got a full answer. I had the same issue and found that this syntax works:
q =*:*& fq = (({
!geofilt sfield = Location pt = 40.68063802521456,
-74.00390625 d = 80.4672
}
AND ClientId : "client1")OR({
!geofilt sfield = Location pt = 36.1146460,
-115.1728160 d = 80.4672
}
AND ClientId : "client2"))
It looks like, you like to run N querys in one request in order to get one result set per query?!
So Field Collapsing ( http://wiki.apache.org/solr/FieldCollapsing ) is what you are looking for. Unfortunately FieldCollapsing is only available from 3.3.
Depending on your needs, maybe counted results from different faceted searches could be also useful?!
What if you moved your second location query into an additional filter query, like below:
q=*:*&fq={!geofilt}&sfield=Location&(ClientId:"client1"&pt=40.68063802521456,-74.00390625&d=80.4672)&fq={!geofilt}&sfield=Location&(ClientId:"client2"&pt=36.1146460,-115.1728160&d=80.4672)
Will that provide the results that you are looking for? It might end up being too limiting, but thought it was worth trying.
You might also try:
q=*:*&fq={!geofilt}&sfield=Location&((ClientId:"client1"&pt=40.68063802521456,-74.00390625&d=80.4672)%20OR%20(ClientId:"client2"&pt=36.1146460,-115.1728160&d=80.4672))

Resources