Neo4j cypher - Compare two collections to get at least one same element - collections

I want to return all users that I follow who are not members of any groups that I am in. If a followed user is a member of even one group that I am in, it should not be returned.
However, I am getting an error:
None.get
Neo.DatabaseError.Statement.ExecutionFailure
when I try this query:
MATCH (g1:groups)<-[:MEMBER_OF]-(u1:users{userid1:"56"})-[:FOLLOWS]->(u2:users)-[:MEMBER_OF]->(g2:groups)
WITH collect(g1.groupid) AS my_groups,u2,collect(g2.groupid) AS foll_groups
WHERE NOT any(t in foll_groups WHERE t IN extract(x IN my_groups))
RETURN u2

Here is one solution:
MATCH (g1:groups)<-[:MEMBER_OF]-(u1:users { userid1:"56" })-[:FOLLOWS]->(u2:users)-[:MEMBER_OF]->(g2:groups)
WITH u2, collect(g2) AS foll_groups, collect(g1) AS my_groups
WITH u2, reduce(dup = FALSE, g IN foll_groups | (dup OR g IN my_groups)) AS has_dup
WHERE NOT has_dup
RETURN u2;

Related

Set multiple threshold on a log based kusto query

I have set up a log-based alert in Microsoft Azure. The deployment of the alerts done via ARM template.
Where you can input your query and set threshold like below.
"triggerThresholdOperator": {
"value": "GreaterThan"
},
"triggerThreshold": {
"value": 0
},
"frequencyInMinutes": {
"value":15
},
"timeWindowInMinutes": {
"value": 15
},
"severityLevel": {
"value": "0"
},
"appInsightsQuery": {
"value": "exceptions\r\n| where A_ != '2000' \r\n| where A_ != '4000' \r\n| where A_ != '3000' "
}
As far as I understand we can only set threshold once ON an entire query.
Questions: I have multiple statements in my query which I am excluding since it's just a noise. But now I want to set a threshold on value 3000 to 5 and also want to set a time-window to 30 in the same query. meaning only exclude 3000 when it occurs 5 times in the last 30 minutes(when query get run).
exceptions
| where A_ != '2000'
| where A_ != '4000'
| where A_ != '3000'
I am pretty sure that I can't set a threshold like this in the query and the only workaround is to create a new alert just for value 3000 and set a threshold in ARM template. I haven't found any heavy threshold/time filters in Aure. Is there any way I can set multiple thresholds and time filters in a single query? which is again getting checked by different threshold and time filetrs in the ARM template.
Thanks.
I don't fully understand your question.
But for your time window question you could do something like
exceptions
| summarize count() by A_, bin(TimeGenerated, 30m)
That way you will get a count of A_ in blocks of 30 minutes.
Another way would be to do:
let Materialized = materialize(
exceptions
| summarize Count=count(A_) by bin(TimeGenerated, 30m)
); 
Materialized | where Count == 10
But then again it all depends on what you would like to achieve
You can easily set that in the query and fire based on the aggregate result.
exceptions
| where timestamp > ago(30m)
| summarize count2000 = countif(A_ == '2000'), count3000 = countif(A_ == '3000'), count4000 = countif(A_ == '4000')
| where count2000 > 5 or count3000 > 3 or count4000 > 4
If the number of results is greater than one than the aggregate condition applies.

What is the "some" meaning in Collect result in Scala

"some" is not a special term which makes the googling seem to just ignore that search.
What I am asking is in my learning below:
b.collect:
Array[(Int, String)] = Array((3,dog), (6,salmon), (3,rat), (8,elephant))
d.collect:
Array[(Int, String)] = Array((3,dog), (3,cat), (6,salmon), (6,rabbit), (4,wolf), (7,penguin))
if I do some join and then collect the result, like b.join(d).collect, I will get the following:
Array[(Int, (String, String))] = Array((6,(salmon,salmon)), (6,(salmon,rabbit)), (3,(dog,dog)), (3,(dog,cat)), (3,(rat,dog)), (3,(rat,cat)))
which seems understandable, however, if I do: b.leftOuterJoin(d).collect, I will get:
Array[(Int, (String, Option[String]))] = Array((6,(salmon,Some(salmon))), (6,(salmon,Some(rabbit))), (3,(dog,Some(dog))), (3,(dog,Some(cat))), (3,(rat,Some(dog))), (3,(rat,Some(cat))), (8,(elephant,None)))
My question is why do I get results seems to be expressed differently, I mean why the second result contains "Some"? what's the difference between with "Some" and without "Some"? Can "Some" be removed? Does "Some" have any impact to any later operations as the content of RDD?
Thank you very much.
When you do the normal join as b.join(d).collect, you get Array[(Int, (String, String))]
This is because of only the same key with RDD b and RDD d so it is always guaranteed to have a value so it returns Array[(Int, (String, String))].
But when you use b.leftOuterJoin(d).collect the return type is Array[(Int, (String, Option[String]))] this is because to handle the null. In leftOuterJoin, there is no guarantee that all the keys of RDD b are available in RDD d, So it is returned as Option[String] which contains two values
Some(String) =>If the key is matched in both RDD
None If the key is present in b and not present in d
You can replace Some by getting the value from it and providing the value in case of None as below.
val z = b.leftOuterJoin(d).map(x => (x._1, (x._2._1, x._2._2.getOrElse("")))).collect
Now you should get Array[(Int, (String, String))] and output as
Array((6,(salmon,salmon)), (6,(salmon,rabbit)), (3,(dog,dog)), (3,(dog,cat)), (3,(rat,dog)), (3,(rat,Some(cat)), (8,(elephant,)))
Where you can replace "" with any other string as you require.
Hope this helps.

What am I doing wrong in the below Prolog code

The Program aims at checking whether a student has taken a specified list of courses or not. But it displays false even if the student has taken that list of courses. What am I doing wrong?
Code:
%Structure Of facts
%student(ID,FirstName,LastName,Advisor,CreditsPassed,GPA,CourseTakenList).
%courses_taken(CourseId,CourseTitle, Credit,Grade, NoOfTimesRepeated).
%Fact
student(20135639,'Sara','Haider','Mr. Hussain Al-Arrayed',98,3.95,
[courses_taken('ITCE418', 'PRODUCTIVITY WITH IS TECHNOLOGY',3,'A', 0),
courses_taken('MATHS101', 'CALCULUS I', 3,'A', 0),
courses_taken('ACC112', 'FINANCIAL ACCOUNTING I', 3, 'A', 0),
courses_taken('ECON140', 'MICROECONOMICS', 3,'A', 0),
courses_taken('ENGL219', 'TECHNICAL REPORT WRITING', 3,'A', 0) ] ).
check_prereq([],Id):- !.
check_prereq([course(P)]|T,Id):-
student(Id,_,_,_,_,_, CoursesTakenList),
member( courses_taken(P,_,_,_,_), CoursesTakenList),
check_prereq(T,Id).
The following query should return true, since the student has taken those courses
?- check_prereq([course('ITCE418'), course('ACC112')],20135639).
false.
Am I doing something wrong?
You need to replace : [course(P)]|T with [course(P)|T]
check_prereq([],_):- !.
check_prereq([course(P)|T],Id):-
student(Id,_,_,_,_,_, CoursesTakenList),
member( courses_taken(P,_,_,_,_), CoursesTakenList),
check_prereq(T,Id).
Also in the first line replaced Id with _ (anonymous variable) in order to get rid of warnings(Singleton variable). Now it is working fine:
?- check_prereq([course('ITCE418'), course('ACC112')],20135639).
true ;
false.
Note that it returns true and asking for more solutions returns false but it succeeds as we expected.

How would you model this non-relational database?

I am making a graph database using Neo4j and I'm wondering what's the best way to model this case:
Person1 > told > quote > to > Person2 > who told it to -> Person3 -> who told it to -> Person4 > Who told it to -> Person1
I've thought about quote being an attribute of link. But then maybe quote needs also to be a node. In this case the edges would be "told" and "was_told". Like:
Person1 -> created > quote
Quote attributes: id, text
Person attributes: id, name
Person2 > told: {to: Person 3} > quote
Person3 > was_told: {by: Person2} > quote
or:
Person3 > told:quote > Person1
What's the best approach to use to model this database?
I think you need the following model:
A fragment (talk) of a conversation (including time)
Who was the speaker of this fragment
Who was an audience of this fragment
Content (quote) of this fragment
For example, here's the code for creating the first fragment:
MERGE (P1:Person {name:'Person1'})
MERGE (P2:Person {name:'Person2'})
MERGE (Q:Quote {name:'Quote1', text:'Quote1 text'})
MERGE (P1)<-[:has_speaker]-(T1:Talk {name:'Talk1', time: 1})-[:has_audience]->(P2)
MERGE (T1)-[:talk_about]->(Q)
Visualization:
The query for the entire life cycle of a quote:
MATCH (Q:Quote {name:'Quote1', text:'Quote1 text'})<-[:talk_about]-(T:Talk)
WITH Q, T
MATCH (P1:Person)<-[:has_speaker]-(T)-[:has_audience]->(P2)
WITH Q, T, P1 as speaker, collect(P2.name) as audience ORDER BY T.time ASC
RETURN Q as quote,
collect( {time: T.time,
speaker: speaker.name,
audience: audience}
) as quoteTimeline

xQuery category nesting issue

I have a problem nesting the result tags in each other the right way.
The result should look like this:
aimed result
<categoryA>
<position>...</position>
<position>...</position>
...
</categoryA>
<categoryB>
<position>...</position>
<position>...</position>
...
</categoryB>
currently I have only managed to get the right results for the positions, the categoryA and B are 1 hierarchic layer higher than the positions. the positions should be nested in the categories. The categories can be referenced by let $y := $d/Bilanz/Aktiva/* (respectively $d$d/Bilanz/Aktiva/LangfristigesVermoegen and $d$d/Bilanz/Aktiva/KurzfristigesVermoegen).
Here is my query:
query
let $d := doc('http://etutor.dke.uni-linz.ac.at/etutor/XML?id=5001')/Bilanzen
let $a02 := $d/Bilanz[#jahr='2002']/Aktiva/*
let $a03 := $d/Bilanz[#jahr='2003']/Aktiva/*
for $n02 in $a02//* , $n03 in $a03//*
(:
where name($n02) = name($n03)
where node-name($n02) = node-name($n03)
:)
where name($n02) = name($n03)
return <position name="{node-name($n02)}">
<j2002>{data($n02/#summe)}</j2002>
<j2003>{data($n03/#summe)}</j2003>
<diff>{data($n03/#summe) - data($n02/#summe)}</diff>
</position>
xml
<Bilanzen>
<Bilanz jahr="2002">
<Aktiva>
<LangfristigesVermoegen>
<Sachanlagen summe="1486575.8"/>
<ImmateriellesVermoegen summe="67767.2"/>
<AssoziierteUnternehmen summe="190826.3"/>
<AndereBeteiligungen summe="507692.7"/>
<Uebrige summe="92916.4"/>
</LangfristigesVermoegen>
<KurzfristigesVermoegen>
<Vorraete summe="78830.9"/>
<Forderungen summe="198210.3"/>
<Finanzmittel summe="181102.0"/>
</KurzfristigesVermoegen>
</Aktiva>
<Passiva>
<Eigenkapital>
<Grundkapital summe="91072.4"/>
<Kapitalruecklagen summe="186789.5"/>
<Gewinnruecklagen summe="798176.2"/>
<Bewertungsruecklagen summe="-34922.4"/>
<Waehrungsumrechnung summe="0"/>
<EigeneAktien summe="0"/>
</Eigenkapital>
<AnteileGesellschafter summe="23613.1"/>
<LangfristigeVerb>
<Finanzverbindlichkeiten summe="680007.1"/>
<Steuern summe="36555.8"/>
<Rueckstellungen summe="429286.1"/>
<Baukostenzuschuesse summe="169246.0"/>
<Uebrige summe="36166.9"/>
</LangfristigeVerb>
<KurzfristigeVerb>
<Finanzverbindlichkeiten summe="14614.6"/>
<Steuern summe="65247.6"/>
<Lieferanten summe="94939.2"/>
<Rueckstellungen summe="123664.8"/>
<Uebrige summe="89464.8"/>
</KurzfristigeVerb>
</Passiva>
</Bilanz>
<Bilanz jahr="2003">
<Aktiva>
<LangfristigesVermoegen>
<Sachanlagen summe="1590313.7"/>
<ImmateriellesVermoegen summe="69693.2"/>
<AssoziierteUnternehmen summe="198224.7"/>
<AndereBeteiligungen summe="418489.3"/>
<Uebrige summe="104566.7"/>
</LangfristigesVermoegen>
<KurzfristigesVermoegen>
<Vorraete summe="20609.8"/>
<Forderungen summe="289458.5"/>
<Finanzmittel summe="302445.9"/>
</KurzfristigesVermoegen>
</Aktiva>
<Passiva>
<Eigenkapital>
<Grundkapital summe="91072.4"/>
<Kapitalruecklagen summe="186789.5"/>
<Gewinnruecklagen summe="875723.4"/>
<Bewertungsruecklagen summe="-15459.5"/>
<Waehrungsumrechnung summe="-633.7"/>
<EigeneAktien summe="0"/>
</Eigenkapital>
<AnteileGesellschafter summe="22669.8"/>
<LangfristigeVerb>
<Finanzverbindlichkeiten summe="733990.2"/>
<Steuern summe="68156.8"/>
<Rueckstellungen summe="395997.2"/>
<Baukostenzuschuesse summe="177338.5"/>
<Uebrige summe="38064.9"/>
</LangfristigeVerb>
<KurzfristigeVerb>
<Finanzverbindlichkeiten summe="6634.7"/>
<Steuern summe="97119.1"/>
<Lieferanten summe="89606.0"/>
<Rueckstellungen summe="128237.5"/>
<Uebrige summe="98495.2"/>
</KurzfristigeVerb>
</Passiva>
</Bilanz>
</Bilanzen>
I would really appreciate some help, i have no clue at all. Thank you.
If I understand you correctly, you want the information about LangfristigesVermoegen (and its children) to be grouped in the output under element categoryA, and the information about Kurzfristigesvermoegen to be grouped under categoryB.
So you will want first of all to do something to generate the categoryA and categoryB elements. For example,
let $d := doc(...)/Bilanzen
return (
<categoryA>{ ... children of category A here ... }</categoryA>,
<categoryB>{ ... children of category B here ... }</categoryB>
)
The positions in each category can be generated using code similar to what you've now got, except that instead of iterating over
for $n02 in $a02//* , $n03 in $a03//*
you will need to iterate over $a02[self::LangfristigesVermoegen]/* for category A, and over $a02[self::KurzfristigesVermoegen]/* for category B (and similarly, of course, for $n02 and $n03).
If the set of categories is not static and you just want to group things in the output using the same grouping elements present in the input, then you'll want an outer structure something like this:
for $assetclass1 in $anno2002/*
let $assetclass2 := $anno2003/*[name() = name($assetclass1)]
return
(element {name($assetclass1)} {
for $old in $assetclass1/*,
$new in $assetclass2/*
where name($old) eq name($new)
return <position name="{node-name($old)}">
<j2002>{data($old/#summe)}</j2002>
<j2003>{data($new/#summe)}</j2003>
<diff>{data($new/#summe) - data($old/#summe)}</diff>
</position>
})

Resources