Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
on 05-23-2021 03:54 AM
Hi all,
I am trying to create a custom function for converting a Linestring to a list of [longitude, latitude] coordinates, but I am having trouble with the type definition for the input and output parameters (input and result). What am I doing wrong?
This is my function definition:
// Convert linestring custom function
CALL apoc.custom.asFunction(
'convert.linestring',
'WITH apoc.text.regexGroups($input, "[-+]?\d+(?:,\d+)?(?:\.\d+)?") AS linestring
RETURN [x IN range(0,size(linestring)-1) WHERE x % 2 = 0 | [toFloat(linestring[x][0]), toFloat(linestring[x+1][0])]] AS result',
'read',
[['result','LIST']],
[['input','STRING']]
);
When I run this, I get the following error:
Wrong argument type: Can't coerce `List{List{String("input"), String("STRING")}}` to Boolean
The Cypher statement in the function definition works fine, e.g. with the following input:
"LINESTRING (35.1110624 31.6963094, 35.1111111 31.696312, 35.1111562 31.6963293, 35.1111823 31.6963494, 35.1112027 31.6963768, 35.1112147 31.6964182)"
I just need to get the description of the input/output parameters right.
Thanks in advance!
Ariel
You probably got confused the declaration of the parameters with apoc.custom.asProcedure
.
In apoc.custom.asFunction
the signature is apoc.custom.asFunction(name :: STRING?, statement :: STRING?, outputs = :: STRING?, inputs = null :: LIST? OF LIST? OF STRING?, forceSingle = false :: BOOLEAN?, description = :: STRING?) :: VOID
.
So, in your case (note that the 3rd parameter (output) is just a string):
CALL apoc.custom.asFunction(
'convert.linestring',
'WITH apoc.text.regexGroups($input, "[-+]?\d+(?:,\d+)?(?:\.\d+)?") AS linestring
RETURN [x IN range(0,size(linestring)-1) WHERE x % 2 = 0 | [toFloat(linestring[x][0]), toFloat(linestring[x+1][0])]] AS result',
'LIST OF ANY',
[['input','STRING']],
true
);
Note the true
as last parameter to avoid to wrap the result in another array,
that is [[[first], [second]...]].
With this one, the output of:
return custom.convert.linestring("LINESTRING (35.1110624 31.6963094, 35.1111111 31.696312, 35.1111562 31.6963293, 35.1111823 31.6963494, 35.1112027 31.6963768, 35.1112147 31.6964182)")
is
[[35.1110624, 31.6963094], [35.1111111, 31.696312], [35.1111562, 31.6963293], [35.1111823, 31.6963494], [35.1112027, 31.6963768], [35.1112147, 31.6964182]]
.
However, as you can see here apoc.custom.asFunction - APOC Documentation
the asFunction
is deprecated, so it's better to use the declareFunction
:
CALL apoc.custom.declareFunction("convert.linestring(input :: STRING) :: LIST OF ANY",
'WITH apoc.text.regexGroups($input, "[-+]?\d+(?:,\d+)?(?:\.\d+)?") AS linestring RETURN [x IN range(0,size(linestring)-1)
WHERE x % 2 = 0 | [toFloat(linestring[x][0]), toFloat(linestring[x+1][0])]] AS result', true)
Thank you very much Guiseppe!