So I have simple graph. The most left nodes are 'Team' class. The second most right (gray one) is 'Sport' class node.
I need to find all Teams which relates to specific Sport
When I have only one Team node this query works:
MATCH {class:Team, as: team} --> {class: Sport, maxDepth: 10}
RETURN team.Abbreviation
After I've added second node of 'Team' class I've started to get this error:
java.lang.RuntimeException: Invalid pattern to match!
If I remove 'maxDepth' it works but returns nothing
What should I do to make it work?
It's definitely a bug, I'm checking it.
As a quick work-around you can add a condition to the first element in the pattern, so that you force the executor to start from there:
MATCH {class:Team, as: team, where:(true)} --> {class: Sport, maxDepth: 10}
RETURN team.Abbreviation
Even better, remove the "class" from the right hand:
MATCH {class:Team, as: team} --> {where: (#class = 'Sport'), maxDepth: 10}
RETURN team.Abbreviation
The problem here is that the pattern is being evaluated in the wrong direction (from right to left), with the above work-around you are forcing OrientDB to evaluate it from left to right
Related
I am new to gremlin.
I am facing issue in fetching the vertex and edges when sometimes edge from a vertex does not exists.
for example bellow query works fine if it gets all the vertex and edges.
but for one use case edge
`.outE("PRODUCES").`as`("produces"))`
does not exists in db.
in that case bellow query doesnt return any result.
I need your help to resolve this issue.
when edges does not exit then i want input_entity and processed_by in result.
janusGraph.traversal().V()
.has("isActive", "true")
.hasLabel("ENTITY").`as`("input_entity")
.outE("PROCESSED_BY").`as`("processed_by")
.inV().`as`("job")
.outE("PRODUCES").`as`("produces")
.select<String>("job").outE("HAS_STATE")
.`as`("job_state_edge").inV().hasLabel("JOB_STATE").`as`("job_state")
.select<String>("input_entity").outE("HAS_STATE")
.`as`("input_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("input_entity_state")
.select<String>("input_entity").outE("CONNECTS_TO").`as`("connects_to")
.inV().hasLabel("ENTITY").has("entityName", TextP.startingWith(rootNamespace))
.`as`("output_entity").outE("HAS_STATE")
.`as`("output_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("output_entity_state")
.select<String>("input_entity","output_entity","processed_by","produces","job","job_state","input_entity_state","output_entity_state","input_entity_state_edge","output_entity_state_edge","job_state_edge","connects_to")
.by(elementMap<Element, Any>()).toList()
with optional
janusGraph.traversal().V()
.has("isActive", "true")
.hasLabel("ENTITY").`as`("input_entity")
.outE("HAS_STATE").`as`("input_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("input_entity_state")
.select<String>("input_entity").outE("PROCESSED_BY").`as`("processed_by")
.inV().`as`("job").outE("HAS_STATE").`as`("job_state_edge").inV().hasLabel("JOB_STATE").`as`("job_state")
.select<String>("job")
.optional(
outE("PRODUCES").`as`("produces")
.select<String>("input_entity").outE("CONNECTS_TO").`as`("connects_to")
.inV().hasLabel("ENTITY").has("entityName", TextP.startingWith(rootNamespace))
.`as`("output_entity").outE("HAS_STATE").`as`("output_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("output_entity_state"))
.select<String>("input_entity","output_entity","processed_by","produces","job","job_state","input_entity_state","output_entity_state","input_entity_state_edge","output_entity_state_edge","job_state_edge","connects_to")
.by(elementMap<Element, Any>()).toList()
There are two Gremlin steps that can help in cases like this. When you have a part of a query that may or may not exist, but you either want the results up to that point if it does not exist or the results afterwards if it does exist, you can wrap that part of the query in an optional step.
For example :
g.V('3').optional(out())
Will either return V['3'] or the adjacent vertices if out yields results.
In cases where you want to select a value that may not exist, you can do something like this:
coalesce(select('a'),constant('No results'))
EDITED to add:
If you need to return multiple results, rather than just using select try a project('a','b,',c') type of approach where each by modulator for the project can contain its own coalesce step.
In RedisGraph using Cypher/python is there a way to
Merge two nodes and move all the relationships from the old node to the new node ?
I suspect there are no pure Cypher solution... in that case what will be the equivalent atomic operations and how to combine them to achieve MERGE-nodes+rel
neo4j have apoc.refactor.mergeNodes(nodes, options), apoc.refactor.mergeRelationships(rels, options), but that doesn't help me !:( because I'm using RedisGraph.
the problem is that in RG I dont have lower level access to do enumeration/iteration to do this programmatically !!
this worked in one direction I have to apply -> the reverse <- second time.
MATCH (old)-[r:q]->(from_to)
WHERE old.val = $old
MATCH (new) WHERE new.val = $new
MERGE (new)-[nr2:q]->(from_to)
SET nr2.val = r.val
DELETE r
any way to combine it in single query ?
I think this can be accomplished in pure Cypher:
MATCH (old {val: 'old'})-[e:E]->(old_to)
MERGE (new {val: 'new'})
CREATE (new)-[e2:E]->(old_to)
SET e2.prop1 = e.prop1, [...]
DELETE e
The chief annoyance here is that all of the edge properties (and node properties, if those are also to be migrated) must be set explicitly, as RedisGraph does not currently support setting property maps.
The problem is described as following:
I want to find some interested paths and get corresponding properties of vertices or edges, the groovy I used is as following:
g.V().has("p_v_name", "d8e5d39d63c580acdb3eb188a1f4a942").
repeat(__.bothE().otherV().simplePath()).
times(3).emit().
has('p_v_tag').
path().
by(
__.project("label", "id", "p_v_black_tag").
by(__.label()).
by(__.id()).
by(__.choose(__.has('p_v_tag'),
__.properties('p_v_tag').project('value').by(__.value()).fold(),
__.constant([])
)
)
).unfold()
The above code gives me following result:
==>[label:v_user_key,id:749577404608,p_v_tag:[[value:PR016],[value:PR033],[value:PR068]]]
==>[label:e_application_id,id:4jjrk79js-9kcn170g-8ph-nvxhl4s0,p_v_tag:[]]
==>[label:v_application_id,id:1871880949872,p_v_tag:[]]
The result is unfolded for easing reading. It's just a path consisted of two nodes and one edge. The source node has a property p_v_tag, it's of multi-properties. The problem is the target node also has the property p_v_tag, but the code does not output the values.
I checked the target node has the property p_v_tag and it's not empty as following:
gremlin> g.V(1871880949872).properties('p_v_tag')
==>vp[p_v_tag->outdated]
I read the document(http://tinkerpop.apache.org/docs/current/reference) over and over but I can't figure out how to make it right, can any body help me or give me some advice?
I'm not sure why that wouldn't work. What happens if you try this workaround to replace:
by(__.choose(__.has('p_v_tag'),
__.properties('p_v_tag').project('value').by(__.value()).fold(),
__.constant([])
)
with:
by(coalesce(properties('p_v_tag').
project('value').
by(__.value()).
fold(),
constant([]))
I'm having difficulty with possible empty relationships in gremlin3.
If I apply a filter on step (hasLabel) and the tranverser contains at least one label, everything runs fine. If not, transverse stops.
If I use optional, my condition gets ignored.
This is my query. The problem is on .hasLabel (within ($ {included})). I can get to work if I remove them.
result = await this.repository`g.V (${organization_uuid}).out()
.until(filter{{it.get().value("name")
.contains(${concept_name})}))
.repeat(inE().otherV().simplePath().timeLimit
(100)).dedup().as('target')
.bothE().as('relation').otherV()
.hasLabel(within(${included}))
.as('descendant').union(select('target',
'relation', 'descendant')
.by(valueMap(true)),outE('related').as
('direct').otherV().as('other')
.select ('direct','other').by(valueMap(true))) `;
I'm trying to populate a list with a dataset and set the selected option with a helper function that compares the current data with another object's data (the 2 objects are linked)
I made the same type of list population with static variables:
Jade-
select(name='status')
option(value='Newly Acquired' selected='{{isCurrentState "Newly Acquired"}}') Newly Acquired
option(value='Currently In Use' selected='{{isCurrentState "Currently In Use"}}') Currently In Use
option(value='Not In Use' selected='{{isCurrentState "Not In Use"}}') Not In Use
option(value='In Storage' selected='{{isCurrentState "In Storage"}}') In Storage
Coffeescript-
"isCurrentState" : (state) ->
return #status == state
This uses a helper isCurrentState to match a given parameter to the same object that my other code is linked to so I know that part works
The code I'm trying to get to work is :
Jade-
select.loca(name='location')
each locations
option(value='#{siteName}' selected='{{isCurrentLocation {{siteName}} }}') #{siteName}
Coffeescript-
"isCurrentLocation": (location) ->
return #locate == location
All the other parts are functioning 100%, but the selected part is not
I've also tried changing the way I entered the selected='' part in a manner of ways such as:
selected='{{isCurrentLocation "#{siteName}" }}'
selected='{{isCurrentLocation "#{siteName} }}'
selected='{{isCurrentLocation {{siteName}} }}'
selected='#{isCurrentLocation "{{siteName}}" }'
selected='#{isCurrentLocation {{siteName}} }'
selected='#{isCurrentLocation #{siteName} }'
Is what I'm trying to do even possible?
Is there a better way of achieving this?
Any help would be greatly appreciated
UPDATE:
Thanks #david-weldon for the quick reply, i've tried this out a bit and realised that I wasn't exactly clear in what I was trying to accomplish in my question.
I have a template "update_building" created with a parameter( a buidling object) with a number of attributes, one of which is "locate".
Locations is another object with a number of attributes as well, one of which is "siteName". One of the siteName == locate and thus i need to pass in the siteName from locations to match it to the current building's locate attribute
Though it doesn't work in the context I want to use it definitely pointed me in a direction I didn't think of. I am looking into moving the parent template(The building) date context as a parameter into the locations template and using it from within the locations template. This is easily fixable in normal HTML spacebars with:
{{>locations parentDataContext/variable}}
Something like that in jade would easily solve this
Short answer
selected='{{isCurrentLocation siteName}}'
Long answer
You don't really need to pass the current location because the helper should know it's own context. Here's a simple (tested) example:
jade
template(name='myTemplate')
select.location(name='location')
each locations
option(value=this selected=isCurrentLocation) #{this}
coffee
LOCATIONS = [
'Newly Acquired'
'Currently In Use'
'Not In Use'
'In Storage'
]
Template.myTemplate.helpers
locations: LOCATIONS
isCurrentLocation: ->
#toString() is Template.instance().location.get()
Template.myTemplate.onCreated ->
#location = new ReactiveVar LOCATIONS[1]
I looked into the datacontexts some more and ended up making the options that populate the select into a different template and giving that template a helper, accessing the template's parent's data context and using that to determine which location the building had saved in it so that I could set that option to selected
Jade-
template(name="location_building_option")
option(value='#{siteName}' selected='{{isSelected}}') #{siteName}
Coffeescript -
Template.location_building_option.helpers
'isSelected': ->
parent = Template.parentData(1)
buildSite = parent.locate
return #siteName == buildSite
Thanks #david-weldon, Your answer helped me immensely to head in the right direction