Variable not defined in query

Hi,

What is the best solution to define the variable collectionRecords in the second part of the query ?

// Collect all cable data for each area
// Part 1
MATCH (cables:Cables)-[:PULLED_TO]->(area:Area)<-[:BELONGS_TO]-(areaDescription:AreaDescription)
WITH areaDescription.deck as deck,
areaDescription.blockNr as block,
area.fromLocation AS to,
count(cables.van_object) AS nrCables,
sum(cables.length) AS length
WITH {Deck: deck,
Block: block,
AreaTo: to,
NrCables: nrCables,
Length: length } as recordSet
ORDER BY recordSet.AreaFrom
WITH COLLECT(recordSet) as collectionRecords
//Part 2
UNWIND ['Main','Local'] as cableIdType
MATCH (cables:Cables{cableType:cableIdType})-[:PULLED_TO]->(area:Area)<-[:BELONGS_TO]-(areaDescription:AreaDescription)
WHERE cables.mainCable IN ['Routed', 'Not Routed', 'Local'] OR cables.pulled IN ['Pulled', 'NOT Pulled']
WITH cables.pulled AS cablePullType,
area.fromLocation AS to,
cableIdType,
count(*) as countOfCables,
sum(cables.length) AS sumOfLengths
WITH {
AreaTo: to,
CableType: cableIdType,
CablePullType: cablePullType,
NrOfCables: countOfCables,
LengthOfCables: sumOfLengths
} as typeData
ORDER BY typeData.AreaTo
WITH COLLECT(typeData) as collectionTypeData
RETURN collectionTypeData, collectionRecords

Variable collectionRecords not defined (line 34, column 28 (offset: 1231))
"RETURN collectionTypeData, collectionRecords"

Kind regards,
Robert

@r.kempers

though neo4j version detail has not been provided should be applicable for most all versions and

It is important to note that WITH affects variables in scope. Any variables not included in the WITH clause are not carried over to the rest of the query. The wildcard * can be used to include all variables that are currently in scope.

as such change

WITH COLLECT(typeData) as collectionTypeData
RETURN collectionTypeData, collectionRecords

to

WITH COLLECT(typeData) as collectionTypeData, collectionRecords
RETURN collectionTypeData, collectionRecords

Thanks for your answer Dana but that is not the solution.

With your suggestion it does have still the same result, "Variable collectionRecords not defined."
WITH COLLECT(typeData) as collectionTypeData, collectionRecords
RETURN collectionTypeData, collectionRecords

In my opinion is not so easy to solve.

@r.kempers

Using Neo4j 5.7.0 I am able to get the following to run and with no error. ( but note as you have provide no version details it is unclear if maybe there is a bug in some other version ) Do you have Neo4j version details?

MATCH (cables:Cables)-[:PULLED_TO]->(area:Area)<-[:BELONGS_TO]-(areaDescription:AreaDescription)
WITH areaDescription.deck as deck,
areaDescription.blockNr as block,
area.fromLocation AS to,
count(cables.van_object) AS nrCables,
sum(cables.length) AS length
WITH {Deck: deck,
Block: block,
AreaTo: to,
NrCables: nrCables,
Length: length } as recordSet
ORDER BY recordSet.AreaFrom
WITH COLLECT(recordSet) as collectionRecords
//Part 2
UNWIND ['Main','Local'] as cableIdType
MATCH (cables:Cables{cableType:cableIdType})-[:PULLED_TO]->(area:Area)<-[:BELONGS_TO]-(areaDescription:AreaDescription)
WHERE cables.mainCable IN ['Routed', 'Not Routed', 'Local'] OR cables.pulled IN ['Pulled', 'NOT Pulled']
WITH cables.pulled AS cablePullType,
area.fromLocation AS to,
cableIdType,
count(*) as countOfCables,
sum(cables.length) AS sumOfLengths, collectionRecords
WITH {
AreaTo: to,
CableType: cableIdType,
CablePullType: cablePullType,
NrOfCables: countOfCables,
LengthOfCables: sumOfLengths
} as typeData, collectionRecords
ORDER BY typeData.AreaTo
WITH COLLECT(typeData) as collectionTypeData, collectionRecords
RETURN collectionTypeData, collectionRecords

Since these two queries are not correlated, you can execute them as two subqueries. This would avoid passing the value through from the first query, through the second, to the result. In this case, I find it simpler to follow.

BTW: Your original query is sorting on recordSet.AreaFrom in Part 1, but I did not see that variable defined. I switched the sorting on AreaTo, which is in the data. You should also be able to sort just on 'to' in each case as well.

call {
    MATCH (cables:Cables)-[:PULLED_TO]->(area:Area)<-[:BELONGS_TO]-(areaDescription:AreaDescription)
    WITH areaDescription.deck as deck,
    areaDescription.blockNr as block,
    area.fromLocation AS to,
    count(cables.van_object) AS nrCables,
    sum(cables.length) AS length
    WITH {
        Deck: deck,
        Block: block,
        AreaTo: to,
        NrCables: nrCables,
        Length: length 
    } as record
    ORDER BY record.AreaTo
    RETURN COLLECT(record) as collectionRecords
}
call {
    UNWIND ['Main','Local'] as cableIdType
    MATCH (cables:Cables{cableType:cableIdType})-[:PULLED_TO]->(area:Area)<-[:BELONGS_TO]-(areaDescription:AreaDescription)
    WHERE cables.mainCable IN ['Routed', 'Not Routed', 'Local'] OR cables.pulled IN ['Pulled', 'NOT Pulled']
    WITH cables.pulled AS cablePullType,
    area.fromLocation AS to,
    cableIdType,
    count(*) as countOfCables,
    sum(cables.length) AS sumOfLengths
    WITH {
        AreaTo: to,
        CableType: cableIdType,
        CablePullType: cablePullType,
        NrOfCables: countOfCables,
        LengthOfCables: sumOfLengths
    } as typeData
    ORDER BY typeData.AreaTo
    RETURN COLLECT(typeData) as collectionTypeData
}
RETURN collectionRecords, collectionTypeData
1 Like

Gary,

Thanks for the example you showed me. Your solution is a great way to solve this kind of issues.

I'm working with a cable database, where cables are connected to equipment which located in an area which has an description.

I like to store cable data per area in the AreaDescription. I was looking for ways to collect the cable data and store it somewhere. for reporting. With the query below I'm able to collect all kind of cable data per area. This is working great. Now I'm wondering what is the best query solution to make the UNION for both record sets. Your way or my way. Your query looks easier to read. What is your opinion ?

// Collect cable information V0.2
Call { UNWIND ['Main','Local'] as cableIdType
       MATCH (areaDescription:AreaDescription)<-[:HAVE_AD]-(area:Area)<-[:PULLED_TO]-(cables:Cables{cableType:cableIdType})
       WHERE cables.mainCable IN ['Routed', 'Not Routed', 'Local'] OR cables.pulled IN ['Pulled', 'NOT Pulled']
       WITH area.fromLocation AS location,
            cables.pulled AS cablePullType,
            cableIdType,
            count(*) as countOfCables, 
            sum(cables.length) AS sumOfLengths
       WITH {
             AreaLocation: location,
             CableType: cableIdType,
             CablePullType: cablePullType,
             NrOfCables: countOfCables, 
            LengthOfCables: sumOfLengths} as typeData
       RETURN typeData as recordSet
       UNION
       UNWIND ['Main','Local'] as cableIdType
       MATCH (areaDescription:AreaDescription)-[:BELONGS_TO]->(area:Area)-[:PULLED_FROM]->(cables:Cables{cableType:cableIdType})
       WHERE cables.mainCable IN ['Routed', 'Not Routed', 'Local'] OR cables.pulled IN ['Pulled', 'NOT Pulled']
       WITH area.fromLocation AS location,
            cables.pulled AS cablePullType,
            cableIdType,
            count(*) as countOfCables, 
            sum(cables.length) AS sumOfLengths
       WITH {
             AreaLocation: location,
             CableType: cableIdType,
             CablePullType: cablePullType,
             NrOfCables: countOfCables, 
             LengthOfCables: sumOfLengths} as typeData
       RETURN typeData as recordSet
     }
WITH recordSet.AreaLocation as location,
     recordSet.CableType as cableType,
     recordSet.CablePullType as cablePullType,
     sum(recordSet.NrOfCables) as nrOfCables,
     sum(recordSet.LengthOfCables) as lengthOfCables
RETURN location, cableType, cablePullType, nrOfCables, lengthOfCables

Kind regards,
Robert