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.

How to condition over each element of a list within a predicate clause?

In
          MATCH p=(:Target)-[r:ASSOCIATION]->(:Phenotype)
For each match, r.association is a List of strings like so:

[
'{
"standardError": 0.0636,
"phenotype": "mortality",
"cohort": "peru",
"coefficient": -0.0053,
}',
'{
"standardError": 0.0456,
"phenotype": "vision impairment",
"cohort": "argentina",
"coefficient": -0.0553,
}',
...
]
I want all p's such that, for instance, at least one cohort in r.association has the value "peru". This is what I have so far:

MATCH p=(:Target)-[:TARGET_ASSOCIATED_TO_PHENOTYPE]->(:Phenotype)
where all(
    r in relationships(p) where    
        apoc.map.get( apoc.convert.fromJsonMap( r.association[ k ] ),"cohort" ) = "peru"
    ) 
RETURN p 

But I do not know how to loop over k such that r satisfies the 'where' clause when at least one of the equalities is true. That is, r is included when k = 1 is true OR k = 2 is true OR k = 3 is true, etc.

Thank you very much,
Rodrigo

4 REPLIES 4

Are you stating that for a given relationship 'r', that the property r.association is a string that represents a json array, where each array element is a json map object?  If true, your requirement is to find paths that have a relationships, such that, at least one of the json maps within the array has 'at least one' property that has the value 'peru'?

Just in case I am correct, here is an example of the logic in isolation that I used to test it. It finds the lists in 'input' that has at least one json map in its list that contains a property whose value equal 'matchString' string.

with ['[
  {"name": "Neo4j", "title": "Elf"},
  {"name": "Graph Data Science Library", "title": "Tootsie"},
  {"name": "Bloom", "title": "Santa Claus" }
]', '[
  {"name": "Neo4j2", "title": "Elf2"},
  {"name": "Graph Data Science Library2", "title": "Tootsie2"},
  {"name": "Bloom", "title2": "Santa Claus2" }
]'] as input, 'Elf' as matchString
unwind input as jsonList
with apoc.convert.fromJsonList(jsonList) as list
where any(x in list where any(y in keys(x) where x[y]=matchString))
return list

 The following query adapts it to your requirement: 

MATCH p=(:Target)-[r:TARGET_ASSOCIATED_TO_PHENOTYPE]->(:Phenotype)
with p, apoc.convert.fromJsonList(r.association) as list
where any(x in list where any(y in keys(x) where x[y]='peru'))
return p

Oops, I reread the posting and I think what you are looking just the 'cohort' property equal 'peru', not any property.

Here is that simplified logic in isolation:

with ['[
  {"name": "Neo4j", "title": "Elf"},
  {"name": "Graph Data Science Library", "title": "Tootsie"},
  {"name": "Bloom", "title": "Santa Claus" }
]', '[
  {"name": "Neo4j2", "title": "Elf2"},
  {"name": "Graph Data Science Library2", "title": "Tootsie2"},
  {"name": "Bloom", "title2": "Santa Claus2" }
]'] as input, 'Tootsie' as matchString
unwind input as jsonList
with apoc.convert.fromJsonList(jsonList) as list
where any(x in list where x.title=matchString)
return list

Adapted to your query, it is the following:

MATCH p=(:Target)-[r:TARGET_ASSOCIATED_TO_PHENOTYPE]->(:Phenotype)
with p, apoc.convert.fromJsonList(r.association) as list
where any(x in list where x.cohort='peru')
return p

I apologize, I did not read the requirement carefully. You property contains a list of strings that represent a json map. My solution above assumed a list of json maps, which neo4j does not support as a property type. 

The following should be correct. I took your example property value and was able to determine if the list contained at least one 'cohort' property equal to 'peru'. 

with [
'{
"standardError": 0.0636,
"phenotype": "mortality",
"cohort": "peru",
"coefficient": -0.0053
}',
'{
"standardError": 0.0456,
"phenotype": "vision impairment",
"cohort": "argentina",
"coefficient": -0.0553
}'] as input, 'peru' as matchString
where any(x in input where apoc.convert.fromJsonMap(x).cohort=matchString)
return input

 Applying the logic to your query, the following should work:

MATCH p=(:Target)-[r:TARGET_ASSOCIATED_TO_PHENOTYPE]->(:Phenotype)
where any(x in r.association where apoc.convert.fromJsonMap(x).cohort='peru')
return p

Sorry for my initial confusion....