Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Q
query-service
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
GraphPolaris
Microservices
query-service
Commits
064aa217
Commit
064aa217
authored
4 weeks ago
by
Dorus
Browse files
Options
Downloads
Patches
Plain Diff
feat: corrected graph udf
parent
cd821dc1
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Pipeline
#147063
passed
4 weeks ago
Stage: tag-release
Stage: get-release-tag
Stage: container-image
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/utils/cypher/udf.ts
+74
-23
74 additions, 23 deletions
src/utils/cypher/udf.ts
with
74 additions
and
23 deletions
src/utils/cypher/udf.ts
+
74
−
23
View file @
064aa217
import
type
{
BackendQueryFormat
,
BackendQueryResultFormat
,
GraphQueryResultMetaFromBackend
,
NodeStruct
}
from
'
ts-common
'
;
import
{
log
}
from
'
../../logger
'
;
import
louvain
from
'
graphology-communities-louvain
'
;
function
applyFilter
(
op
:
string
,
value
:
number
,
threshold
:
number
)
{
...
...
@@ -41,7 +40,7 @@ export const runUdfs = async (
);
for
(
const
udf
of
query
.
udf
)
{
log
.
warn
(
'
Running UDF
'
,
query
.
udf
,
allUniqueNodes
);
console
.
log
(
'
Running UDF
'
,
query
.
udf
,
allUniqueNodes
);
const
leftLabel
=
allUniqueNodes
[
udf
.
leftId
].
label
;
const
rightLabel
=
udf
.
rightId
?
allUniqueNodes
[
udf
.
rightId
].
label
:
undefined
;
...
...
@@ -61,7 +60,7 @@ export const runUdfs = async (
nodeMap
[
edge
.
from
]
=
nodeMap
[
edge
.
from
]
+
1
;
}
log
.
warn
(
'
nodeMap
'
,
nodeMap
,
udf
.
right
,
query
.
udf
);
console
.
log
(
'
nodeMap
'
,
nodeMap
,
udf
.
right
,
query
.
udf
);
// Apply the operation filter based on degree
//
result
.
nodes
=
nodes
.
filter
(
node
=>
{
...
...
@@ -74,37 +73,89 @@ export const runUdfs = async (
const
nodeIds
=
new
Set
(
result
.
nodes
.
map
(
node
=>
node
.
_id
));
result
.
edges
=
edges
.
filter
(
edge
=>
nodeIds
.
has
(
edge
.
from
)
&&
nodeIds
.
has
(
edge
.
to
));
}
else
if
(
udf
.
type
==
"
community_detection
"
)
{
const
{
Graph
}
=
require
(
'
graphology
'
);
const
graph
=
new
Graph
();
result
.
nodes
.
forEach
(
node
=>
graph
.
addNode
(
node
.
_id
));
result
.
edges
.
forEach
(
edge
=>
graph
.
addEdge
(
edge
.
from
,
edge
.
to
));
if
(
udf
.
type
===
'
community_detection
'
)
{
const
nodes
=
result
.
nodes
;
const
edges
=
result
.
edges
;
// Detect communities and community size
const
communities
=
louvain
(
graph
);
const
communitySizes
:
Record
<
string
,
number
>
=
{};
Object
.
values
(
communities
).
forEach
(
communityId
=>
{
communitySizes
[
communityId
]
=
(
communitySizes
[
communityId
]
||
0
)
+
1
;
// convert graph to adjacency list
const
adjacencyList
=
{};
nodes
.
forEach
(
node
=>
{
adjacencyList
[
node
.
_id
]
=
[];
});
// Filter nodes based on community size
result
.
nodes
=
result
.
nodes
.
filter
(
node
=>
{
if
(
node
.
label
!==
leftLabel
)
return
true
;
const
nodeCommunity
=
communities
[
node
.
_id
];
const
communitySize
=
communitySizes
[
nodeCommunity
]
||
0
;
edges
.
forEach
(
edge
=>
{
adjacencyList
[
edge
.
from
].
push
(
edge
.
to
);
adjacencyList
[
edge
.
to
].
push
(
edge
.
from
);
});
const
communities
=
{};
nodes
.
forEach
(
node
=>
{
communities
[
node
.
_id
]
=
node
.
_id
;
});
let
changed
=
true
;
const
maxIterations
=
10
;
let
iterations
=
0
;
while
(
changed
&&
iterations
<
maxIterations
)
{
changed
=
false
;
iterations
++
;
for
(
const
nodeId
in
adjacencyList
)
{
const
neighbors
=
adjacencyList
[
nodeId
];
if
(
neighbors
.
length
===
0
)
continue
;
// Count neighbors in each community
const
communityCounts
=
{};
neighbors
.
forEach
(
neighborId
=>
{
const
communityId
=
communities
[
neighborId
];
communityCounts
[
communityId
]
=
(
communityCounts
[
communityId
]
||
0
)
+
1
;
});
// Find the community with the most neighbors
let
bestCommunity
=
communities
[
nodeId
];
let
maxCount
=
0
;
for
(
const
communityId
in
communityCounts
)
{
if
(
communityCounts
[
communityId
]
>
maxCount
)
{
maxCount
=
communityCounts
[
communityId
];
bestCommunity
=
communityId
;
}
}
// Move to the best community if it's different
if
(
bestCommunity
!==
communities
[
nodeId
])
{
communities
[
nodeId
]
=
bestCommunity
;
changed
=
true
;
}
}
}
// Count nodes in each community
const
communitySizes
=
{};
for
(
const
nodeId
in
communities
)
{
const
communityId
=
communities
[
nodeId
];
communitySizes
[
communityId
]
=
(
communitySizes
[
communityId
]
||
0
)
+
1
;
}
result
.
nodes
=
nodes
.
filter
(
node
=>
{
const
communityId
=
communities
[
node
.
_id
];
const
communitySize
=
communitySizes
[
communityId
]
||
0
;
// filter communities based on size
return
applyFilter
(
udf
.
op
,
communitySize
,
udf
.
right
);
});
//
Filter edg
es
//
Update edges to only include those connecting remaining nod
es
const
nodeIds
=
new
Set
(
result
.
nodes
.
map
(
node
=>
node
.
_id
));
result
.
edges
=
result
.
edges
.
filter
(
edge
=>
nodeIds
.
has
(
edge
.
from
)
&&
nodeIds
.
has
(
edge
.
to
)
);
result
.
edges
=
edges
.
filter
(
edge
=>
nodeIds
.
has
(
edge
.
from
)
&&
nodeIds
.
has
(
edge
.
to
));
}
}
log
.
warn
(
result
.
nodes
.
length
,
result
.
edges
.
length
);
console
.
log
(
result
.
nodes
.
length
,
result
.
edges
.
length
);
return
result
;
};
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment