2016-06-03 16 views
1

ich Neo4j bin mit Anwendungsdaten zu speichern und Bild unten zeigt die GraphstrukturNeo4j Chiffre Abfrage läuft sehr langsam

graph

Jeder Kreis ist ein Knoten und jeder Pfeil zeigt eine Beziehung und Beziehungstyp ist oben definiert . Es definiert auch many to many or one to many or one to one relationship for nodes.

Was ich gerne aus der Grafik abrufen würde.

Ich möchte für ein Unternehmen alle Positionen aufzulisten und jede Position eine Reihe von Benutzer und jeder Benutzer eine Reihe von Feedback für jedes Interview Runde haben, wie unter

position ---> candidate1 interview round name (Telephonic) question1 answer1 and answer given by user1 question1 answer1 and answer given by user2 interview round name (HR Round) question1 answer1 and answer given by user1 question1 answer1 and answer given by user2 candidate2 interview round name (Telephonic) question1 answer1 and answer given by user1 question1 answer1 and answer given by user2 interview round name (HR Round) question1 answer1 and answer given by user1 question1 answer1 and answer given by user2 . . .

Viele Kandidaten wird keine Interviewrunden haben, denn für diese Kandidaten sollten die Runden null sein.

Unten ist die Abfrage, die ich verwende, um die Daten abzurufen, die ich brauche.

MATCH (comp:Company {dId: "155dyv1wgT"})<-[:`POSITION_COMPANY`]-(pos: Position {status: 'OPEN'})-[:`POSITION_WORKFLOW`]->(:WorkFlow)-[:`WORKFLOW_CANDIDATE-WORKFLOW`]->(cw : CandidateWorkFlow)-[:`CANDIDATE-WORKFLOW_COMPANY-CANDIDATE`]->(cc : CompanyCandidate) 

where ((not (has(cc.isSpam) or has(cc.isTrash))) OR (cc.isSpam=false and cc.isTrash=false)) and pos.positionType IN ['PUBLIC','DISCRETE'] with distinct comp, {dId: pos.dId, title: pos.title} as pos, cw, cc 

OPTIONAL MATCH (cw)-[:`CANDIDATE_WORKFLOW_INTERVIEW`]->(inwrkflw: InterviewWorkFlow)-[:`INTERVIEW_ROUND`]->(intrnd: InterviewRound)-[:`INTERVIEW_ROUND_FEEDBACK`]->(ffform: FeedbackForm)-[:`FEEDBACK_QUESTION`]-(ffq: Question) 

OPTIONAL MATCH (inwrkflw)-[:`INTERVIEW_WORKFLOW_FEEDBACK`]-(ff:Feedback) 

OPTIONAL MATCH (iwr : User)-[:`FEEDBACK_BY`]->(ff)-[:`FEEDBACK_ANSWER`]->(answer:Answer)-[:`QUESTION_ANSWER`]->(ffq) 

with collect({answer : answer.value, rating: answer.rating, question : ffq.qText, givenBy : iwr.fullName, type: ffq.questionType, givenOn: answer.lastModifiedDate}) as rnds, cc, pos, intrnd 

with filter(rnd IN rnds WHERE rnd.type = 'COMMENTS') as comments, filter(rnd IN rnds WHERE rnd.type = 'LINEAR_GENERIC') as ratings, cc, pos, intrnd 

with distinct collect({roundName: intrnd.name, ratings: ratings, comments: comments}) as rounds, cc, pos 

return collect({cc: cc, rounds: rounds}) as data, pos.dId as posId, pos.title as posTitle 

dId ist einzigartig auf jedem Knoten.

Das Problem mit dieser Abfrage ist für kleine Datenmenge sagen wir 1000 Kandidaten mit 10 Positionen wird es gut laufen. Bei großen Datensätzen dauert es jedoch zu lange, Ergebnisse zu liefern. Ich wartete sogar 5 Minuten in der neo4j Konsole für die Antwort, aber es gab keine Antwort in 5 Minuten.

Die Anwendung hat keine 1000 Kandidaten. Die Anzahl der Kandidaten wird bis mindestens 100000 gehen und ich kann maximal 1 Million pro Firma annehmen.

Ich habe verschiedene Möglichkeiten versucht, diese Abfrage zu optimieren, konnte aber keine Antwort erhalten.

Die Antwort-SLA sollte innerhalb von 20 Sekunden liegen.

Meine Fragen sind

  1. Wie kann ich diese Abfrage optimieren, um die Ergebnisse zu erhalten, ich will?
  2. Was ist falsch in der aktuellen Abfrage?
+1

können Sie Ihre Abfrage mit PROFILE ausführen und das Ergebnis teilen? –

+0

können Sie Ihre Datenbank mit mir teilen? Michael bei neo4j.com –

+0

welche Version verwenden Sie? –

Antwort

0

Zuerst habe ich Ihre db auf 2.3 aktualisiert.3

Ihr Modell besteht aus zwei Teilgraphen, die

  1. die Meta-Informationen des Einstellungsprozesses
  2. die konkrete Feedback/Antworten für einen Kandidaten beide

Für Ihr Unternehmen beschreiben sind ziemlich groß:

  1. 235600 Pfade von Firma zu Frage über den Interviewprozess
  2. 83937 von Unternehmen über den Beton in Frage beantwortet

von denen jede etwa 1 s dauert

zu berechnen Wenn Sie nur über sie abfragen, werden Sie die Zahlen multiplizieren aus, die zu 20 Mrd. Wege nach oben endet .

, die ganz für immer nimmt

Meine Lösung zu berechnen, wurde zum ersten Mal ein Subgraphen abzufragen und es dann zur Seite (in einer Aggregation) setzen und dann die zweite Subgraphen Abfrage

Zuerst habe ich sie zusammengebracht durch passende Antworten auf die Fragen (die in ein ExpandInto Betrieb gedreht wird)

WHERE (answer)-[:QUESTION_ANSWER]->(ffq)

die die Abfrage Finish in etwa 15 Sekunden hergestellt.

Dann dehnte ich die konkrete (Antwort) Subgraphen einen Schritt auf die Fragen und brachte sie zusammen mit der Frage selbst (ffq = ffq2)

Dadurch wird die gesamte Ausführungszeit brachte bis auf 1,6 Sekunden. Hier

ist die letzte Abfrage:

MATCH (comp:Company {dId: "155dyv1wgT"})<-[:`POSITION_COMPANY`]-(pos: Position {status: 'OPEN'})-[:`POSITION_WORKFLOW`]->(:WorkFlow)-[:`WORKFLOW_CANDIDATE-WORKFLOW`]->(cw : CandidateWorkFlow)-[:`CANDIDATE-WORKFLOW_COMPANY-CANDIDATE`]->(cc : CompanyCandidate) 

where ((not (has(cc.isSpam) or has(cc.isTrash))) OR (cc.isSpam=false and cc.isTrash=false)) and pos.positionType IN ['PUBLIC','DISCRETE'] with distinct comp, {dId: pos.dId, title: pos.title} as pos, cw, cc 

with distinct comp, {dId: pos.dId, title: pos.title} as pos, cw, cc 

MATCH (cw)-[:`CANDIDATE_WORKFLOW_INTERVIEW`]->(inwrkflw) 

MATCH (inwrkflw)-[:`INTERVIEW_ROUND`]->(intrnd)-[:`INTERVIEW_ROUND_FEEDBACK`]->(ffform)-[:`FEEDBACK_QUESTION`]-(ffq) 

WITH comp,pos, cw, cc,inwrkflw, collect({round:intrnd,form:ffform,question:ffq}) as workflow_questions 

MATCH (inwrkflw)-[:`INTERVIEW_WORKFLOW_FEEDBACK`]-(ff:Feedback) 
MATCH (iwr : User)-[:`FEEDBACK_BY`]->(ff)-[:`FEEDBACK_ANSWER`]->(answer:Answer)-[:`QUESTION_ANSWER`]->(ffq2) 

UNWIND workflow_questions as wq 

WITH comp,pos, cw, cc,inwrkflw, iwr,ff,answer, wq.round as intrnd, wq.form as ffform, wq.question as ffq 

WHERE ffq2 = ffq 

with collect({answer : answer.value, rating: answer.rating, question : ffq.qText, givenBy : iwr.fullName, type: ffq.questionType, givenOn: answer.lastModifiedDate}) as rnds, cc, pos, intrnd 

with filter(rnd IN rnds WHERE rnd.type = 'COMMENTS') as comments, filter(rnd IN rnds WHERE rnd.type = 'LINEAR_GENERIC') as ratings, cc, pos, intrnd 

with collect({roundName: intrnd.name, ratings: ratings, comments: comments}) as rounds, cc, pos 

return collect({cc: cc, rounds: rounds}) as data, pos.dId as posId, pos.title as posTitle;