Get relationship node from 2 edges in 1 cypher query - graph

I need a cypher query that retrieves the weight of two edges at the same time. This is my attempt:
MATCH (n:User)-[r:VIEWED|UPDATED]->(f:File) WHERE f.id IN 'some_id','another_id'] RETURN n, r.weight, ORDER BY r.weight DESC
The result contains two lines for each user who updated and viewed the file. However, I want the result in one line. For example: user: x - updated: 12 - viewed:15
How can I do this?

UPDATED:
try:
MATCH (f:File)
OPTIONAL MATCH (n:User)-[r1:VIEWED]->(f:File)
OPTIONAL MATCH (n:User)-[r2:UPDATED]->(f:File)
where f.id IN ['some_id','another_id']
return n,
sum(r1.weight) as totalViewedWeight,
sum(r2.weight) as totalUpdatedWeight

MATCH (n:User)-[r:VIEWED|UPDATED]->(f:File)
WHERE f.id IN ['some_id','another_id']
RETURN n, collect(type(r)), collect(r.weight)

Related

REGEXP_SUBSTR return all matches (mariaDB)

I need to get all the matches of a regular expression in a text field in a MariaDB table. As far as I know REGEXP_SUBSTR is the way to go to get the value of the match of a regular expression in a text field, but it always returns after the first match and I would like to get all matches.
Is there any way to do this in MariaDB?
An example of the content of the text field would be:
#Generation {
// 1
True =>
`CP?:24658` <= `CPV?:24658=57186`;
//`CP?23432:24658` <= `CPV?:24658=57186`
// 2
`CP?:24658` <> `CPV?:24658=57178` =>
`CP?:24656` <> `CPV?:24656=57169`;
And the select expression that I'm using right now is:
select REGEXP_SUBSTR(textfield,'CP\\?(?:\\d*:)*24658') as my_match
from table
where id = 1243;
Which at the moment returns just the first match:
CP?:24658
And I would like it to return all matches:
CP?:24658
CP?23432:24658
CP?:24658
Use just REGEXP to find the interesting rows. Put those into a temp table
Repeatedly process the temp table -- but remove the SUBSTR as you use it.
What will you be doing with each substr? Maybe that will help us devise a better approach.

Queries to be tested in Neo4j

Why I can't get any results with this queries? What I'm doing wrong here?
QUERY 1
MATCH (person:Person)-[:PRS_knows_PRS*1..2]-(friend:Person),
(friend)<-[:CMT_hasCreator_PRS]-(friendPost:Post)-[:PST_hasTag_TAG]->(knownTag:Tag {nameTag:2})
WHERE not(person=friend)
MATCH (friendPost)-[:PST_hasTag_TAG]->(commonTag:Tag)
WHERE not(commonTag=knownTag)
WITH DISTINCT commonTag, knownTag, friend
MATCH (commonTag)<-[:PST_hasTag_TAG]-(commonPost:Post)-[:PST_hasTag_TAG]->(knownTag)
WHERE (commonPost)-[:CMT_hasCreator_PRS]->(friend)
RETURN
commonTag.nameTag AS tagName,
count(commonPost) AS postCount
ORDER BY postCount DESC, tagName ASC
LIMIT 3
QUERY 2
MATCH (person:Person)-[:PRS_knows_PRS*1..2]-(friend:Person)
WHERE not(person=friend)
WITH DISTINCT friend
MATCH (friend)-[worksAt:PRS_worksAt_ORG]->(company:Organisation)-[:ORG_isLocatedIn_PLC]->(:Country {name:{3}})
WHERE worksAt.workFromPWAO < {2}
RETURN
friend.idPerson AS friendId,
friend.firstNamePerson AS friendFirstName,
friend.lastNamePerson AS friendLastName,
worksAt.workFromPWAO AS workFromYear,
company.nameOrganisation AS companyName
ORDER BY workFromYear ASC, friendId ASC, companyName DESC
LIMIT 4
I have this nodes, property Keys and relatioship types:
Could you please help me with this problem?
On your query you use this relationship name:
worksAt:PRS_worksAt_ORG
but on your screen shot of the properties the relationship is called 'PRS_workAt_ORG' without the 's' on workAt.
Maybe that's what's missing on the second query?
Usually it helps to build up the queries step by step.
Then you see where they stop returning data.
A PROFILE (prefix) of your queries should also help to see where it starts to return ZERO rows.
Could also be a case-typo in one of the labels and rel-types.

Neo4j - querying N items per group

The following is my query:
MATCH (u:User{id:1})-[r:FOLLOWS]->(p:Publisher)<-[:PUBLISHED]-(i:Item)-[:TAGGED]->(t:Tag)<-[f:FOLLOWS]-u
RETURN a, count(t) ORDER BY count(k) DESC LIMIT 100
So User can follow Publisher and a Tag. The query find the items, that user may like by counting matching tags.
Suppose there two properties, MIN and MAX, on relationship u-r->p. These properties specify, how many items user wants to see from each publisher. How can I rewrite the query to allow this?
Here is one thought. Say for instance that the FOLLOWS relationship has a min value and a max value set. You could use the following query to limit the data that is returned by the query based on those values. I have not rewritten the entire query to include the tags and a limit there either.
// find the user and the publisher and the relationship
// which has the min/max parameters
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
// macth the items that the publisher published
match p-[:PUBLISHED]-(i:Item)
// order them just because we can
with u, p, r, i
order by i.name
// collect the ordered items as the total list of items
with u, p, r, collect(i.name) as items
// make sure the collection is >= the minimum size of the list
// if so then return the items in the collection up to the max length
// otherwise return and empty collection
// you might want to do something else
with u, p, r, case
when length(items) >= r.min then items[..r.max]
else []
end as items
return u.name, p.name, r.min, r.max, items
The unfortunate thing about this is that you have already performed the query to get the items and are just filtering them out for display purposes. It would be nice to know the person's preference before hand so you could apply the max limit in the query for the items using limit and a parameter. This would eliminate unnecessary database hits. Depending on the publisher there could be many, many items and limiting them up front might be advantageous.
Here are a couple of variations to experiment with too. You could also do something like this...
// slight variation where the minimum is enforced with where instead of case
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
match p-[:PUBLISHED]-(i:Item)
with u, p, r, i
order by i.name
with u, p, r, collect(i.name) as items
where length(items) >= r.min
return u.name, p.name, items[..r.max]
or even this...
// only results actually between the min and max are returned
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
match p-[:PUBLISHED]-(i:Item)
with u, p, r, i
order by i.name
with u, p, r, collect(i.name) as items
where length(items) >= r.min
and length(items) <= r.max
return u.name, p.name, items[..r.max]

cypher: how to return distinct relationship types?

How to return the distinct relationship types from all paths in cypher?
Example query:
MATCH p=(a:Philosopher)-[*]->(b:SchoolType)
RETURN DISTINCT EXTRACT( r in RELATIONSHIPS(p)| type(r) ) as RelationshipTypes
This returns a collection for each path p.
I would like to return a single collection contain the distinct relationship types across all collections.
Here is a link to a graph gist to run the query-
http://gist.neo4j.org/?7851642
You might first collect all relationships on the matched path to a collection "allr", and then get the collection of distinct type(r) from the collection of all relationships,
MATCH p=(a:Philosopher)-[rel*]->(b:SchoolType)
WITH collect(rel) AS allr
RETURN Reduce(allDistR =[], rcol IN allr |
reduce(distR = allDistR, r IN rcol |
distR + CASE WHEN type(r) IN distR THEN [] ELSE type(r) END
)
)
Note, each element 'rcol' in the collection "allr" is in turn a collection of relationships on each matched path.

Cypher Order By Number of Paths

Let's say I have a graph of movies and directors, where movies are connected to each other by co-viewership. I want to find similar directors, i.e. directors whose films tend to be watched together.
START n=node:index(Name="Steven Spielberg") MATCH n-->m--l<--o RETURN o;
This gets me all of the related directors, but how do I order them by the number of paths that connect them? Bonus points if I can also take weight of the tie between films into consideration.
count(*) is the number of paths that start with n and end with o
START n=node:index(Name="Steven Spielberg")
MATCH n-->m--l<--o
RETURN o,count(*)
order by count(*) desc;
with weights on the relationships
START n=node:index(Name="Steven Spielberg")
MATCH path=n-->m--l<--o
RETURN o,sum(reduce(sum=0,r in rels(path) : sum+r.weight)) as weight
ORDER BY weight desc;
START n=node:index(Name="Steven Spielberg")
MATCH path=n-->m--l<--o
RETURN o
ORDER BY length(path);

Resources