cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

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

Comments
giuseppe_villan
Graph Fellow

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)
ariel_degraaf
Node Clone

Thank you very much Guiseppe!

Version history
Last update:
‎05-23-2021 03:54 AM
Updated by:
Contributors