mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-08 15:30:55 +00:00
feat(neo4j): improve neo4j read query performance by specifying labels (#10593)
This commit is contained in:
parent
9b247e1031
commit
36ae5afbb5
@ -377,11 +377,14 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
graphFilters.getAllowedEntityTypes(), direction),
|
graphFilters.getAllowedEntityTypes(), direction),
|
||||||
"maxHops", maxHops));
|
"maxHops", maxHops));
|
||||||
|
|
||||||
|
final String entityType = entityUrn.getEntityType();
|
||||||
|
|
||||||
if (lineageFlags == null
|
if (lineageFlags == null
|
||||||
|| (lineageFlags.getStartTimeMillis() == null && lineageFlags.getEndTimeMillis() == null)) {
|
|| (lineageFlags.getStartTimeMillis() == null && lineageFlags.getEndTimeMillis() == null)) {
|
||||||
// if no time filtering required, simply find all expansion paths to other nodes
|
// if no time filtering required, simply find all expansion paths to other nodes
|
||||||
final var statement =
|
final var statement =
|
||||||
"MATCH (a {urn: $urn}) "
|
String.format(
|
||||||
|
"MATCH (a:%s {urn: $urn}) "
|
||||||
+ "CALL apoc.path.spanningTree(a, { "
|
+ "CALL apoc.path.spanningTree(a, { "
|
||||||
+ " relationshipFilter: $relationshipFilter, "
|
+ " relationshipFilter: $relationshipFilter, "
|
||||||
+ " labelFilter: $labelFilter, "
|
+ " labelFilter: $labelFilter, "
|
||||||
@ -390,7 +393,8 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
+ "}) "
|
+ "}) "
|
||||||
+ "YIELD path "
|
+ "YIELD path "
|
||||||
+ "WITH a, path AS path "
|
+ "WITH a, path AS path "
|
||||||
+ "RETURN a, path, last(nodes(path));";
|
+ "RETURN a, path, last(nodes(path));",
|
||||||
|
entityType);
|
||||||
return Pair.of(statement, parameterMap);
|
return Pair.of(statement, parameterMap);
|
||||||
} else {
|
} else {
|
||||||
// when needing time filtering, possibility on multiple paths between two
|
// when needing time filtering, possibility on multiple paths between two
|
||||||
@ -413,7 +417,8 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
// exploration, not
|
// exploration, not
|
||||||
// after path exploration is done)
|
// after path exploration is done)
|
||||||
final var statement =
|
final var statement =
|
||||||
"MATCH (a {urn: $urn}) "
|
String.format(
|
||||||
|
"MATCH (a:%s {urn: $urn}) "
|
||||||
+ "CALL apoc.path.subgraphNodes(a, { "
|
+ "CALL apoc.path.subgraphNodes(a, { "
|
||||||
+ " relationshipFilter: $relationshipFilter, "
|
+ " relationshipFilter: $relationshipFilter, "
|
||||||
+ " labelFilter: $labelFilter, "
|
+ " labelFilter: $labelFilter, "
|
||||||
@ -432,7 +437,8 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
+ " ($startTimeMillis <= rt.createdOn <= $endTimeMillis OR "
|
+ " ($startTimeMillis <= rt.createdOn <= $endTimeMillis OR "
|
||||||
+ " $startTimeMillis <= rt.updatedOn <= $endTimeMillis) "
|
+ " $startTimeMillis <= rt.updatedOn <= $endTimeMillis) "
|
||||||
+ " ) "
|
+ " ) "
|
||||||
+ "RETURN a, path, b;";
|
+ "RETURN a, path, b;",
|
||||||
|
entityType);
|
||||||
|
|
||||||
// provide dummy start/end time when not provided, so no need to
|
// provide dummy start/end time when not provided, so no need to
|
||||||
// format clause differently if either of them is missing
|
// format clause differently if either of them is missing
|
||||||
@ -487,10 +493,19 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
matchTemplate = "MATCH (src %s)-[r%s %s]->(dest %s)%s";
|
matchTemplate = "MATCH (src %s)-[r%s %s]->(dest %s)%s";
|
||||||
}
|
}
|
||||||
|
|
||||||
final String returnNodes =
|
String srcNodeLabel = StringUtils.EMPTY;
|
||||||
String.format(
|
// Create a URN from the String. Only proceed if srcCriteria is not null or empty
|
||||||
"RETURN dest, type(r)"); // Return both related entity and the relationship type.
|
if (StringUtils.isNotEmpty(srcCriteria)) {
|
||||||
final String returnCount = "RETURN count(*)"; // For getting the total results.
|
final String urnValue =
|
||||||
|
sourceEntityFilter.getOr().get(0).getAnd().get(0).getValue().toString();
|
||||||
|
try {
|
||||||
|
final Urn urn = Urn.createFromString(urnValue);
|
||||||
|
srcNodeLabel = urn.getEntityType();
|
||||||
|
matchTemplate = matchTemplate.replace("(src ", "(src:%s ");
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
log.error("Failed to parse URN: {} ", urnValue, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String relationshipTypeFilter = "";
|
String relationshipTypeFilter = "";
|
||||||
if (!relationshipTypes.isEmpty()) {
|
if (!relationshipTypes.isEmpty()) {
|
||||||
@ -500,7 +515,20 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
String whereClause = computeEntityTypeWhereClause(sourceTypes, destinationTypes);
|
String whereClause = computeEntityTypeWhereClause(sourceTypes, destinationTypes);
|
||||||
|
|
||||||
// Build Statement strings
|
// Build Statement strings
|
||||||
String baseStatementString =
|
String baseStatementString;
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(srcNodeLabel)) {
|
||||||
|
baseStatementString =
|
||||||
|
String.format(
|
||||||
|
matchTemplate,
|
||||||
|
srcNodeLabel,
|
||||||
|
srcCriteria,
|
||||||
|
relationshipTypeFilter,
|
||||||
|
edgeCriteria,
|
||||||
|
destCriteria,
|
||||||
|
whereClause);
|
||||||
|
} else {
|
||||||
|
baseStatementString =
|
||||||
String.format(
|
String.format(
|
||||||
matchTemplate,
|
matchTemplate,
|
||||||
srcCriteria,
|
srcCriteria,
|
||||||
@ -508,9 +536,13 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
edgeCriteria,
|
edgeCriteria,
|
||||||
destCriteria,
|
destCriteria,
|
||||||
whereClause);
|
whereClause);
|
||||||
|
}
|
||||||
log.info(baseStatementString);
|
log.info(baseStatementString);
|
||||||
|
|
||||||
|
final String returnNodes =
|
||||||
|
"RETURN dest, type(r)"; // Return both related entity and the relationship type.
|
||||||
|
final String returnCount = "RETURN count(*)"; // For getting the total results.
|
||||||
|
|
||||||
final String resultStatementString =
|
final String resultStatementString =
|
||||||
String.format("%s %s SKIP $offset LIMIT $count", baseStatementString, returnNodes);
|
String.format("%s %s SKIP $offset LIMIT $count", baseStatementString, returnNodes);
|
||||||
final String countStatementString = String.format("%s %s", baseStatementString, returnCount);
|
final String countStatementString = String.format("%s %s", baseStatementString, returnCount);
|
||||||
@ -571,10 +603,11 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
public void removeNode(@Nonnull final Urn urn) {
|
public void removeNode(@Nonnull final Urn urn) {
|
||||||
|
|
||||||
log.debug(String.format("Removing Neo4j node with urn: %s", urn));
|
log.debug(String.format("Removing Neo4j node with urn: %s", urn));
|
||||||
|
final String srcNodeLabel = urn.getEntityType();
|
||||||
|
|
||||||
// also delete any relationship going to or from it
|
// also delete any relationship going to or from it
|
||||||
final String matchTemplate = "MATCH (node {urn: $urn}) DETACH DELETE node";
|
final String matchTemplate = "MATCH (node:%s {urn: $urn}) DETACH DELETE node";
|
||||||
final String statement = String.format(matchTemplate);
|
final String statement = String.format(matchTemplate, srcNodeLabel);
|
||||||
|
|
||||||
final Map<String, Object> params = new HashMap<>();
|
final Map<String, Object> params = new HashMap<>();
|
||||||
params.put("urn", urn.toString());
|
params.put("urn", urn.toString());
|
||||||
@ -605,19 +638,20 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
|
|
||||||
// also delete any relationship going to or from it
|
// also delete any relationship going to or from it
|
||||||
final RelationshipDirection relationshipDirection = relationshipFilter.getDirection();
|
final RelationshipDirection relationshipDirection = relationshipFilter.getDirection();
|
||||||
|
final String srcNodeLabel = urn.getEntityType();
|
||||||
|
|
||||||
String matchTemplate = "MATCH (src {urn: $urn})-[r%s]-(dest) RETURN type(r), dest, 2";
|
String matchTemplate = "MATCH (src:%s {urn: $urn})-[r%s]-(dest) RETURN type(r), dest, 2";
|
||||||
if (relationshipDirection == RelationshipDirection.INCOMING) {
|
if (relationshipDirection == RelationshipDirection.INCOMING) {
|
||||||
matchTemplate = "MATCH (src {urn: $urn})<-[r%s]-(dest) RETURN type(r), dest, 0";
|
matchTemplate = "MATCH (src:%s {urn: $urn})<-[r%s]-(dest) RETURN type(r), dest, 0";
|
||||||
} else if (relationshipDirection == RelationshipDirection.OUTGOING) {
|
} else if (relationshipDirection == RelationshipDirection.OUTGOING) {
|
||||||
matchTemplate = "MATCH (src {urn: $urn})-[r%s]->(dest) RETURN type(r), dest, 1";
|
matchTemplate = "MATCH (src:%s {urn: $urn})-[r%s]->(dest) RETURN type(r), dest, 1";
|
||||||
}
|
}
|
||||||
|
|
||||||
String relationshipTypeFilter = "";
|
String relationshipTypeFilter = "";
|
||||||
if (!relationshipTypes.isEmpty()) {
|
if (!relationshipTypes.isEmpty()) {
|
||||||
relationshipTypeFilter = ":" + StringUtils.join(relationshipTypes, "|");
|
relationshipTypeFilter = ":" + StringUtils.join(relationshipTypes, "|");
|
||||||
}
|
}
|
||||||
final String statement = String.format(matchTemplate, relationshipTypeFilter);
|
final String statement = String.format(matchTemplate, srcNodeLabel, relationshipTypeFilter);
|
||||||
|
|
||||||
final Map<String, Object> params = new HashMap<>();
|
final Map<String, Object> params = new HashMap<>();
|
||||||
params.put("urn", urn.toString());
|
params.put("urn", urn.toString());
|
||||||
@ -626,7 +660,7 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
if (!neo4jResult.isEmpty()) {
|
if (!neo4jResult.isEmpty()) {
|
||||||
String removeMode = neo4jResult.get(0).values().get(2).toString();
|
String removeMode = neo4jResult.get(0).values().get(2).toString();
|
||||||
if (removeMode.equals("2")) {
|
if (removeMode.equals("2")) {
|
||||||
final String matchDeleteTemplate = "MATCH (src {urn: $urn})-[r%s]-(dest) DELETE r";
|
final String matchDeleteTemplate = "MATCH (src:%s {urn: $urn})-[r%s]-(dest) DELETE r";
|
||||||
relationshipTypeFilter = "";
|
relationshipTypeFilter = "";
|
||||||
if (!relationshipTypes.isEmpty()) {
|
if (!relationshipTypes.isEmpty()) {
|
||||||
relationshipTypeFilter =
|
relationshipTypeFilter =
|
||||||
@ -636,7 +670,7 @@ public class Neo4jGraphService implements GraphService {
|
|||||||
+ StringUtils.join(relationshipTypes, "|r_");
|
+ StringUtils.join(relationshipTypes, "|r_");
|
||||||
}
|
}
|
||||||
final String statementNoDirection =
|
final String statementNoDirection =
|
||||||
String.format(matchDeleteTemplate, relationshipTypeFilter);
|
String.format(matchDeleteTemplate, srcNodeLabel, relationshipTypeFilter);
|
||||||
runQuery(buildStatement(statementNoDirection, params)).consume();
|
runQuery(buildStatement(statementNoDirection, params)).consume();
|
||||||
} else {
|
} else {
|
||||||
for (Record typeDest : neo4jResult) {
|
for (Record typeDest : neo4jResult) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user