How can I pass a node or relationship to a inner apoc call?

apoc
cypher

(Guilherme Junqueira) #1

Guys,

I am trying to implement a 'edit function' on my web application, but I having a hard time trying to figure out how to pass my node and relationship to a inner apoc.refactor.to call.

My query is as follows:

WITH
  'mas_muovebrasil'          as pTenantName,
  87                         as pOrgId,
  'Teste edição instituição' as pOrgName,
  '111'                      as pOrgCNPJ,
  'outro'                    as pOrgKindAutoname,
  'Grupo de amigos'          as pOrgKindDetail
MATCH
  (t:TenantMAS)<-[rel_seen:as_seen_by]-(org:Organization)-[rel_class:is_classified_as]->(old_class:OrganizationKind),
  (new_class:OrganizationKind)
WHERE
  t.name = pTenantName
  and org.id = pOrgId
  and new_class.auto_name = pOrgKindAutoname
SET
  org.name = pOrgName,
  org.cnpj = pOrgCNPJ,
  rel_class.specific_classification = pOrgKindDetail
WITH
  t,
  rel_seen,
  org,
  rel_class,
  old_class,
  new_class
CALL apoc.do.when(
  old_class <> new_class,
  'CALL apoc.refactor.to(rel, toNode) YIELD input, output',
  '',
  '{rel: rel_class, toNode: new_class}'
) YIELD value
RETURN *

I am getting the following error:

Neo.ClientError.Statement.SyntaxError: Type mismatch: expected Map, Node or Relationship but was String

Should I "capture" the node and the relationship in the apoc.do.when right before the call apoc.reafactor.to or is there a way of passing it along to the inner call?

Thanks in advance,


(Guilherme Junqueira) #2

Guys,

I think I just spotted two single quotation marks where they should not have been.

Sorry for my mistake. Let's see if I advance with that.

Thanks


(Michael Hunger) #3

Yes, well spotted.
You should also use parameters on the outside query and not a WITH with literal values :slight_smile:


(Guilherme Junqueira) #4

You are right, Michael!

We cannot do this at the moment because we are connecting to two neo4j instances, one through a ruby gem and the other through the http endpoint (the one related to this query).

We have plans on phasing out one of the instances and using the gem and the BOLT protocol for the remaining. Then, we will do things more properly regarding this matter...

Unless you tell me I can do this right now with the HTTP endpoint! (I did not find anything related to this on my researches.


(Michael Hunger) #5

The ruby gem and http endpoints all support query parameters.


(Guilherme Junqueira) #6

That's really nice! I thought they were exclusive of the BOLT protocol.

If you allow me one more question, I would like to know how to proper implement this.

If I am not mistaken, I have to make one call setting the parameters, one with the query itself and another one "cleaning after myself". Is this right?

Currently I just have to make one call, although I know I have the downside of "forcing" Neo4j to always "hard parse" my queries...

Any documentation regarding my doubts will be highly appreciated!

Thanks in advance,


(Michael Hunger) #7

Not really sure what you mean? Do you have a concrete example?

Can't you pass the parameter hash to both in the client?


(Guilherme Junqueira) #8

Michael, let me try with the query:

WITH
  'mas_muovebrasil'            as pTenantName,
  101                          as pAgentId,
  'Alameda Franca'             as pActAddrStreetName,
  '406'                        as pActAddrNumber,
  'Jardins'                    as pActAddrNeighborhood,
  '00000-000'                  as pActAddrPostalCode,
   0.0                         as pActAddrLatitude,
   0.0                         as pActAddrLongitude,
  'sao-paulo-sp'               as pActAddrCity
MATCH
  (c:City {normalized_name: pActAddrCity}),
  (:TenantMAS {name: pTenantName})<-[:as_seen_by]-(:LocalAgent {id: pAgentId})-[:exercises]->(i:Influence)
MERGE
  (new_addr:Address {
    street_name:  pActAddrStreetName,
    number:       pActAddrNumber,
    neighborhood: pActAddrNeighborhood,
    cep:          pActAddrPostalCode
  })-[:belongs_to]->(c)
ON CREATE SET
  new_addr.latitude  = pActAddrLatitude,
  new_addr.longitude = pActAddrLongitude
WITH
  i,
  new_addr
MATCH
  (i)-[rel_sup:supported_on]->(old_addr:Address)
WITH
  rel_sup,
  old_addr,
  new_addr
CALL apoc.do.when(
  old_addr <> new_addr,
  'CALL apoc.refactor.to(rel_to_change, toNode) YIELD input, output, error RETURN error',
  '',
  {rel_to_change: rel_sup, toNode: new_addr}
) YIELD value
RETURN
  new_addr

(please, don't mind the absence of parameters. I will fix this eventually)

I want to be able to plot my graph in both situations, either when it gets refactored or not, but I was not able to achieve this properly...

Thanks!


(Michael Hunger) #9

You probably don't want to return the error but the new relationship
and in the else branch return the existing relationship?


(Guilherme Junqueira) #10

Maybe I didn't do it properly, but I tried exactly this before.

It was then that I tried to understand the "meaning" of the output values of the APOC procedures...

I will look into this again when I rewrite this query to use parameters.

Thanks,