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))) `;
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.
I'm switching over to using the Auto-IVC component as opposed to the IndepVar component. I'd like to be able to get a list of the promoted output names of the Auto-IVC component, so I can then use them to go and pull the appropriate value out of a configuration file and set the values that way. This will get rid of some boilerplate.
p.model._auto_ivc.list_outputs()
returns an empty list. It seems that p.model__dict__ has this information encoded in it, but I don't know exactly what is going on there so I am wondering if there is an easier way to do it.
To avoid confusion from future readers, I assume you meant that you wanted the promoted input names for the variables connected to the auto_ivc outputs.
We don't have a built-in function to do this, but you could do it with a bit of code like this:
seen = set()
for n in p.model._inputs:
src = p.model.get_source(n)
if src.startswith('_auto_ivc.') and src not in seen:
print(src, p.model._var_allprocs_abs2prom['input'][n])
seen.add(src)
assuming 'p' is the name of your Problem instance.
The code above just prints each auto_ivc output name followed by the promoted input it's connected to.
Here's an example of the output when run on one of our simple test cases:
_auto_ivc.v0 par.x
I have a webpage with a combobox to sort a list by Price, Name,... The list is in many pages, so I need to get all elements first and after, I will sort by and check if the elements are correct. Right?
I am trying to do it and navigate for all pages and get all elements. But it is only taking the elements in first page. I am totally new in Robot framework.
Does anyone have a suggestion how I can do it?
${name_list_actual} Create List
${cnt_pages}= Get Element Count //div[#class='container index-new-p']/div/nav[#class='text-center']/ul/li/*
Log To Console ${cnt_pages}
:FOR ${n} IN RANGE 1 ${cnt_pages}
\ Click link //div[#class='container index-new-p']/div/nav/ul/li[${n}]/a
\ ${cnt}= Get Element Count //*[#class="title"]/*
:FOR ${i} IN RANGE 1 ${cnt}
\ ${get_names} Get Element Attribute //table[#class='result-table']/tbody/tr[${i}]/td/div/div[2]/div/a text
\ Append To List ${name_list_actual} ${get_names}
${get_names}= Select All From List //table[#class='result-table']/tbody/tr[${i}]/td/div/div[2]/div/a
\ Log To Console ${name_list_actual}
\ Continue For Loop
Thanks so much
First and foremost, by your code sample's indent it looks like you're doing nested for loops - an outer one for the changing the pages, and an inner that'll get the text in each row. The thing is - Robot Framework doesn't support nested for loops - see the documentation.
What happened on execution is the first loop (the pagination) ran with just two statements and finished:
\ Click link //div[#class='container index-new-p']/div/nav/ul/li[${n}]/a
\ ${cnt}= Get Element Count //*[#class="title"]/*
Then all the rest were executed as part of the second.
A solution would be to have a keyword "Get All Values In The Table" that'll hold the inner loop, and call it in the current outer, which will paginate.
Another issue - you're using IN RANGE, passing 1 as start and ${cnt} as end; if it had value of 4, you probably expect the tracking variable to get all values from 1 to 4.
Yet range works with the first argument inclusive, and up to - but not getting to - the second argument; thus it covers the range 1 to 3. To salvage that, you'd need to set the upper bound to cnt+1, e.g. ${cnt + 1}.
Minor stuff:
You have a statement that's within the loop block, but not prefixed with \:
${get_names}= Select All From List //table[#class='result-table']/tbody/tr[${i}]/td/div/div[2]/div/a
I'm surprised it didn't give you a syntax error - it effectively breaks the loop, and the framework should complain the next lines are prefixed as if in a loop, but one is not started.
-
When you are changing the pages by the click, you are not making sure the UI has loaded the data for the new page. If this happens through ajax calls, you may very well be working with the previous page's data, thinking it is the new one - the selenium click returns control very fast, and the operands for getting the text are running - while the UI still waits for the new data and is displaying the previous one.
-
In RF version 3.1 the loop syntax is different - the block members are not prefixed with \, and it's closed with an END statement.
I'd suggest to migrate to it - a) the current one is going to be eventually deprecated, and b) in the new one the nesting would have been marked as syntax error (you're starting a new loop without END-ing the running one), instead of silently passing with unexpected behavior.
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
The following code produces an endless loop of repeated child_added, though I never add a child. The nodes are removed. I just loop forever. How can I fix this?
//notifications branch is pre-populated when I get here:
notifications.startAt(null).on('child_added', processNotification, logError);
function processNotification(notification)
{
removeNotification(notification);
}
function removeNotification(notification)
{
var child = notifications.child(notification.name());
console.log("REMOVING", child.toString());
child.remove();
}
What I log is the same four nodes (A,B,C,D) being removed:
REMOVING https://my.firebaseio.com/experimental/-JVMi0_4poXfOWUt5g49 - A
REMOVING https://my.firebaseio.com/experimental/-JVMi1Y_bFwZAkffRel4 - B
REMOVING https://my.firebaseio.com/experimental/-JVMi2lyhKj8z27ik71x - C
REMOVING https://my.firebaseio.com/experimental/-JVMhzazdgHYAstqxu8L - D
REMOVING https://my.firebaseio.com/experimental/-JVMi0_4poXfOWUt5g49 - A
REMOVING https://my.firebaseio.com/experimental/-JVMi1Y_bFwZAkffRel4 - B
REMOVING https://my.firebaseio.com/experimental/-JVMi2lyhKj8z27ik71x - C
REMOVING https://mu.firebaseio.com/experimental/-JVMhzazdgHYAstqxu8L - D
...
I was able to reproduce the problem. I think it is caused by the fact that the Query tries to keep items in its "window" when you remove one.
You can work around this problem by using a once('value' instead of on('child_added', like this:
notifications.startAt(null).once('value', processNotifications);
function processNotifications(notifications)
{
notifications.forEach(function(notification) {
notification.ref().remove();
});
}
Since the value only fires once, it will not be interfering with the remove operation.
Ultimately, I just dropped the query and went with normal processing, dropping the "startAt(null)":
notifications.on('child_added', processNotification, logError);
It's not obvious that the behavior will be different from the documentation, but the startAt(null) does not produce the same behavior (though in thoery it should). I would love to see this better documented.