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
2950efcc
Commit
2950efcc
authored
4 months ago
by
Marcos Pieras
Browse files
Options
Downloads
Patches
Plain Diff
fix: handle objects as it was in go
parent
b8bcfc36
No related branches found
Branches containing commit
Tags
v1.18.0
Tags containing commit
No related merge requests found
Pipeline
#141509
passed
4 months ago
Stage: tag-release
Stage: get-release-tag
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/utils/cypher/queryParser.ts
+123
-122
123 additions, 122 deletions
src/utils/cypher/queryParser.ts
with
123 additions
and
122 deletions
src/utils/cypher/queryParser.ts
+
123
−
122
View file @
2950efcc
import
{
Record
,
Node
,
Relationship
,
Path
,
PathSegment
,
isRelationship
,
isNode
,
isPath
,
isPathSegment
,
Integer
}
from
'
neo4j-driver
'
;
import
{
Record
,
Node
,
Relationship
,
Path
,
PathSegment
,
isRelationship
,
isNode
,
isPath
,
isPathSegment
,
Integer
}
from
"
neo4j-driver
"
;
import
{
log
}
from
'
../../logger
'
;
import
{
log
}
from
"
../../logger
"
;
import
type
{
EdgeQueryResult
,
NodeQueryResult
}
from
'
ts-common
'
;
import
type
{
EdgeQueryResult
,
NodeQueryResult
}
from
"
ts-common
"
;
import
type
{
GraphQueryResultFromBackend
}
from
'
ts-common
'
;
import
type
{
GraphQueryResultFromBackend
}
from
"
ts-common
"
;
export
function
parseCypherQuery
(
result
:
Record
[],
returnType
:
"
nodelink
"
|
"
table
"
=
"
nodelink
"
):
GraphQueryResultFromBackend
{
export
function
parseCypherQuery
(
result
:
Record
[],
returnType
:
"
nodelink
"
|
"
table
"
=
"
nodelink
"
):
GraphQueryResultFromBackend
{
try
{
try
{
try
{
try
{
switch
(
returnType
)
{
switch
(
returnType
)
{
case
"
nodelink
"
:
case
"
nodelink
"
:
return
parseNodeLinkQuery
(
result
);
return
parseNodeLinkQuery
(
result
);
case
"
table
"
:
case
"
table
"
:
// TODO: add table support later
// TODO: add table support later
// return parseGroupByQuery(result.records as any);
// return parseGroupByQuery(result.records as any);
log
.
error
(
`Table format not supported yet`
);
log
.
error
(
`Table format not supported yet`
);
throw
new
Error
(
"
Table format not supported yet
"
);
throw
new
Error
(
"
Table format not supported yet
"
);
default
:
default
:
log
.
error
(
`Error Unknown query Format`
);
log
.
error
(
`Error Unknown query Format`
);
throw
new
Error
(
"
Unknown query Format
"
);
throw
new
Error
(
"
Unknown query Format
"
);
}
}
}
catch
(
err
)
{
log
.
error
(
`Parsing failed
${
err
}
`
);
throw
err
;
}
}
catch
(
err
)
{
}
catch
(
err
)
{
log
.
error
(
`
Error executing query`
,
err
);
log
.
error
(
`
Parsing failed
${
err
}
`
);
throw
err
;
throw
err
;
}
}
}
catch
(
err
)
{
log
.
error
(
`Error executing query`
,
err
);
throw
err
;
}
}
}
function
parseNodeLinkQuery
(
results
:
Record
[]):
GraphQueryResultFromBackend
{
function
parseNodeLinkQuery
(
results
:
Record
[]):
GraphQueryResultFromBackend
{
let
nodes
:
NodeQueryResult
[]
=
[];
let
nodes
:
NodeQueryResult
[]
=
[];
let
edges
:
EdgeQueryResult
[]
=
[];
let
edges
:
EdgeQueryResult
[]
=
[];
let
nodeIds
:
Set
<
string
>
=
new
Set
();
let
nodeIds
:
Set
<
string
>
=
new
Set
();
let
edgeIds
:
Set
<
string
>
=
new
Set
();
let
edgeIds
:
Set
<
string
>
=
new
Set
();
const
result
:
GraphQueryResultFromBackend
=
{
nodes
,
edges
};
const
result
:
GraphQueryResultFromBackend
=
{
nodes
,
edges
};
for
(
let
i
=
0
;
i
<
results
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
results
.
length
;
i
++
)
{
const
resList
=
results
[
i
];
const
resList
=
results
[
i
];
for
(
let
j
=
0
;
j
<
resList
.
length
;
j
++
)
{
for
(
let
j
=
0
;
j
<
resList
.
length
;
j
++
)
{
const
res
=
resList
.
get
(
j
);
const
res
=
resList
.
get
(
j
);
parseNodeLinkEntity
(
res
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
res
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
}
}
}
}
return
result
;
return
result
;
}
}
function
parseNodeLinkEntity
(
res
:
Node
|
Relationship
|
Path
|
PathSegment
,
nodes
:
NodeQueryResult
[],
edges
:
EdgeQueryResult
[],
nodeIds
:
Set
<
string
>
,
edgeIds
:
Set
<
string
>
):
void
{
function
parseNodeLinkEntity
(
if
(
isRelationship
(
res
))
{
res
:
Node
|
Relationship
|
Path
|
PathSegment
,
const
neoEdge
=
parseEdge
(
res
);
nodes
:
NodeQueryResult
[],
if
(
!
edgeIds
.
has
(
neoEdge
.
_id
))
{
edges
:
EdgeQueryResult
[],
edgeIds
.
add
(
neoEdge
.
_id
);
nodeIds
:
Set
<
string
>
,
edges
.
push
(
neoEdge
);
edgeIds
:
Set
<
string
>
}
):
void
{
}
else
if
(
isNode
(
res
))
{
if
(
isRelationship
(
res
))
{
const
neoNode
=
parseNode
(
res
);
const
neoEdge
=
parseEdge
(
res
);
if
(
!
nodeIds
.
has
(
neoNode
.
_id
))
{
if
(
!
edgeIds
.
has
(
neoEdge
.
_id
))
{
nodeIds
.
add
(
neoNode
.
_id
);
edgeIds
.
add
(
neoEdge
.
_id
);
nodes
.
push
(
neoNode
);
edges
.
push
(
neoEdge
);
}
}
}
else
if
(
isPath
(
res
))
{
}
else
if
(
isNode
(
res
))
{
parseNodeLinkEntity
(
res
.
start
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
const
neoNode
=
parseNode
(
res
);
for
(
const
segment
of
res
.
segments
)
{
if
(
!
nodeIds
.
has
(
neoNode
.
_id
))
{
parseNodeLinkEntity
(
segment
.
relationship
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
nodeIds
.
add
(
neoNode
.
_id
);
parseNodeLinkEntity
(
segment
.
end
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
nodes
.
push
(
neoNode
);
}
}
parseNodeLinkEntity
(
res
.
end
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
}
else
if
(
isPath
(
res
))
{
}
else
if
(
isPathSegment
(
res
))
{
parseNodeLinkEntity
(
res
.
start
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
res
.
start
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
for
(
const
segment
of
res
.
segments
)
{
parseNodeLinkEntity
(
res
.
relationship
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
segment
.
relationship
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
res
.
end
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
segment
.
end
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
}
else
{
log
.
warn
(
`Ignoring Unknown type
${
res
}
`
);
}
}
parseNodeLinkEntity
(
res
.
end
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
}
else
if
(
isPathSegment
(
res
))
{
parseNodeLinkEntity
(
res
.
start
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
res
.
relationship
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
parseNodeLinkEntity
(
res
.
end
,
nodes
,
edges
,
nodeIds
,
edgeIds
);
}
else
{
log
.
warn
(
`Ignoring Unknown type
${
res
}
`
);
}
}
}
function
parseNode
(
node
:
Node
):
NodeQueryResult
{
function
parseNode
(
node
:
Node
):
NodeQueryResult
{
return
{
return
{
_id
:
node
.
identity
.
toString
(),
_id
:
node
.
identity
.
toString
(),
label
:
node
.
labels
[
0
],
// TODO: only using first label
label
:
node
.
labels
[
0
],
// TODO: only using first label
attributes
:
Object
.
fromEntries
(
Object
.
entries
(
node
.
properties
)?.
map
(([
k
,
v
])
=>
{
attributes
:
Object
.
fromEntries
(
if
(
Integer
.
isInteger
(
v
))
{
Object
.
entries
(
node
.
properties
)?.
map
(([
k
,
v
])
=>
{
return
[
k
,
v
.
toNumber
()];
if
(
Integer
.
isInteger
(
v
))
{
}
return
[
k
,
v
.
toNumber
()];
}
if
(
v
instanceof
Object
)
{
return
[
k
,
v
];
// TODO: for now, we don't support nested objects
})
return
[
k
,
JSON
.
stringify
(
v
)];
),
}
};
return
[
k
,
v
];
})),
};
}
}
function
parseEdge
(
edge
:
Relationship
):
EdgeQueryResult
{
function
parseEdge
(
edge
:
Relationship
):
EdgeQueryResult
{
return
{
return
{
_id
:
edge
.
identity
.
toString
(),
_id
:
edge
.
identity
.
toString
(),
label
:
edge
.
type
,
label
:
edge
.
type
,
from
:
edge
.
start
.
toString
(),
from
:
edge
.
start
.
toString
(),
to
:
edge
.
end
.
toString
(),
to
:
edge
.
end
.
toString
(),
attributes
:
{
...
edge
.
properties
,
type
:
edge
.
type
},
attributes
:
{
...
edge
.
properties
,
type
:
edge
.
type
},
};
};
}
}
function
parseGroupByQuery
(
results
:
Record
<
any
,
string
>
[]):
any
{
function
parseGroupByQuery
(
results
:
Record
<
any
,
string
>
[]):
any
{
// TODO: not tested, since we don't use this yet
// TODO: not tested, since we don't use this yet
let
groupKey
:
string
;
let
groupKey
:
string
;
let
byKey
:
string
;
let
byKey
:
string
;
const
group
:
string
[]
=
[];
const
group
:
string
[]
=
[];
const
by
:
string
[]
=
[];
const
by
:
string
[]
=
[];
const
result
:
{
[
key
:
string
]:
any
}
=
{};
const
result
:
{
[
key
:
string
]:
any
}
=
{};
if
(
results
[
0
].
keys
.
length
!==
2
)
{
if
(
results
[
0
].
keys
.
length
!==
2
)
{
throw
new
Error
(
"
invalid result format
"
);
throw
new
Error
(
"
invalid result format
"
);
}
}
// Checks if the first letter of the first key is either an e or an r, since that would make it the By-key
// Checks if the first letter of the first key is either an e or an r, since that would make it the By-key
// By-keys start with e0_attr or r0_attr and group keys with an aggregation funcion such as AVG_attr or MIN_attr
// By-keys start with e0_attr or r0_attr and group keys with an aggregation funcion such as AVG_attr or MIN_attr
// This will work when an aggregation function starts with an E or R, since e != E
// This will work when an aggregation function starts with an E or R, since e != E
if
(
results
[
0
].
keys
[
0
][
0
]
===
'
e
'
||
results
[
0
].
keys
[
0
][
0
]
===
'
r
'
)
{
if
(
results
[
0
].
keys
[
0
][
0
]
===
"
e
"
||
results
[
0
].
keys
[
0
][
0
]
===
"
r
"
)
{
byKey
=
results
[
0
].
keys
[
0
];
byKey
=
results
[
0
].
keys
[
0
];
groupKey
=
results
[
0
].
keys
[
1
];
groupKey
=
results
[
0
].
keys
[
1
];
}
else
{
}
else
{
byKey
=
results
[
0
].
keys
[
1
];
byKey
=
results
[
0
].
keys
[
1
];
groupKey
=
results
[
0
].
keys
[
0
];
groupKey
=
results
[
0
].
keys
[
0
];
}
// Form proper result structure
for
(
const
res
of
results
)
{
const
g
=
res
.
get
(
groupKey
);
const
b
=
res
.
get
(
byKey
);
if
(
g
!==
null
&&
b
!==
null
)
{
group
.
push
(
g
.
toString
());
by
.
push
(
b
.
toString
());
}
}
}
// Form proper result structure
result
[
"
group
"
]
=
{
name
:
groupKey
,
values
:
group
};
for
(
const
res
of
results
)
{
result
[
"
by
"
]
=
{
name
:
byKey
,
values
:
by
};
const
g
=
res
.
get
(
groupKey
);
const
b
=
res
.
get
(
byKey
);
if
(
g
!==
null
&&
b
!==
null
)
{
return
result
;
group
.
push
(
g
.
toString
());
}
by
.
push
(
b
.
toString
());
}
}
result
[
"
group
"
]
=
{
name
:
groupKey
,
values
:
group
};
result
[
"
by
"
]
=
{
name
:
byKey
,
values
:
by
};
return
result
;
}
\ No newline at end of file
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