Retrieving single property value in Gremlin query closure works, but retrieving valueMap() fails yields Exception - titan

Using the Titan 1.0.0 Gremlin shell I can retrieve a single property value from an edge from within a closure. But trying to access the valueMap() fails with an exception.
Works:
gremlin> t.E().hasLabel("TRUSTS").has('NOT_VALID_BEFORE').each( { trustEdge -> t.E().has('EDGE_GROUP_ID', trustEdge.value('EDGE_GROUP_ID')).hasNot('NOT_VALID_BEFORE').each({println it.value('EDGE_ID')}) } )
Yields exception (only difference is in the right most closure 'it.valueMap()' vs 'it.value('..')'):
gremlin> t.E().hasLabel("TRUSTS").has('NOT_VALID_BEFORE').each( { trustEdge -> t.E().has('EDGE_GROUP_ID', trustEdge.value('EDGE_GROUP_ID')).hasNot('NOT_VALID_BEFORE').each( { println it.valueMap() } ) } )
No signature of method: com.thinkaurelius.titan.graphdb.relations.StandardEdge.valueMap() is applicable for argument types: () values: []
Possible solutions: value(java.lang.String)
Display stack trace? [yN]
gremlin>
But it is not that in general I would be unable to get to the valueMap of the edge:
gremlin> t.E().hasLabel("TRUSTS").has('NOT_VALID_BEFORE').each( { trustEdge -> t.E().has('EDGE_GROUP_ID', trustEdge.value('EDGE_GROUP_ID')).hasNot('NOT_VALID_BEFORE').each( { println it } ) } )
e[215rmh-oe094-1d05-9i0][40964296-MANAGED->12312]
gremlin> t.E('215rmh-oe094-1d05-9i0').valueMap()
==>[MANAGE_INFORM:false, NOT_VALID_AFTER:1669873006000, MANAGE_MANAGERS:false, MANAGE_AUTHENTICATION_MEANS:true, CREATED_AT:1487683094863, RELATIONSHIP_ROLE:FAMILY_DOCTOR, MANAGE_TRUST:true, UPDATED_AT:1487683094915, MANAGE_REPRESENTATION:false, EDGE_ID:122881049, VERIFIED:true, EDGE_GROUP_ID:122881049]
Is this a bug or am I doing something wrong here?
A little context, just in case the query does not even do what I think it does:
What I think I am doing here is looking up all edges with label "TRUSTS" that have a property NOT_VALID_BEFORE. For each of those edges I look up all edges that share the same edge group ID value and check if they also have a property NOT_VALID_BEFORE, printing those to the console that do not have the property set.

When you start iterating with each(), every item you manipulate inside the closure is "off the traversal" -- that is, you're working with an Edge object, not an GraphTraversal object.
Edge has a value() method similar to the GraphTraversal, but it does not have a valueMap() method. You could use ElementHelper.propertyValueMap() instead.
Here's a quick example:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.E().valueMap()
==>[weight:0.5]
==>[weight:1.0]
==>[weight:0.4]
==>[weight:1.0]
==>[weight:0.4]
==>[weight:0.2]
gremlin> g.E().each{ edge -> println ElementHelper.propertyValueMap(edge) };[]
[weight:0.5]
[weight:1.0]
[weight:0.4]
[weight:1.0]
[weight:0.4]
[weight:0.2]

Related

Call a PostgreSQL function and get result back with no loop

I have a simple rust program that interacts with a PostgreSQL database.
The actual code is:
for row in &db_client.query("select magic_value from priv.magic_value();", &[]).unwrap()
{
magic_value = row.get("magic_value");
println!("Magic value is = {}", magic_value);
}
And.. it works. But I don't like it: I know this function will return one and only one value.
From the example I found, for example here: https://docs.rs/postgres/latest/postgres/index.html
and here: https://tms-dev-blog.com/postgresql-database-with-rust-how-to/
You always have a recordset to loop on.
Which is the clean way to call a function without looping?
query returns a Result<Vec<Row>, _>. You are already unwrapping the Vec, so you can just use it directly instead of looping. By turning the Vec into an owning iterator yourself, you can even easily obtain a Row instead of a &Row.
magic_value = db_client.query("select magic_value from priv.magic_value();", &[])
.unwrap() // -> Vec<Row>
.into_iter() // -> impl Iterator<Item=Row>
.next() // -> Option<Row>
.unwrap() // -> Row
.get("magic_value");

"IllegalArgumentException: Argument is not an array" error in processing when using append();

My code is as so...
ArrayList<Ray> rays = new ArrayList<Ray>();
Particle() {
for(int a=0; a < 360; a+=10) {
append(rays, new Ray(position, radians(a)));
}
}
I'm initializing an ArrayList of the class Ray. Then I run through a for loop and am attempting to
append a new Ray() to the list. I get no errors in the editor but whenever I run the code I get the error message: IllegalArgumentException: Argument is not an array
I've looked around and nothing seems to answer my question. Why is this happening?
The append function is for use with arrays (e.g.: rays[]). However rays is an ArrayList. Hence, you need to use the add method:
append(rays, new Ray(position, radians(a)));
rays.add(new Ray(position, radians(a));

Filtering a collection of IO's: List[IO[Page]] scala

I am refactoring a scala http4s application to remove some pesky side effects causing my app to block. I'm replacing .unsafeRunSync with cats.effect.IO. The problem is as follows:
I have 2 lists: alreadyAccessible: IO[List[Page]] and pages: List[Page]
I need to filter out the pages that are not contained in alreadyAccessible.
Then map over the resulting list to "grant Access" in the database to these pages. (e.g. call another method that hits the database and returns an IO[Page].
val addable: List[Page] = pages.filter(p => !alreadyAccessible.contains(p))
val added: List[Page] = addable.map((p: Page) => {
pageModel.grantAccess(roleLst.head.id, p.id) match {
case Right(p) => p
}
})
This is close to what I want; However, it does not work because filter requires a function that returns a Boolean but alreadyAccessible is of type IO[List[Page]] which precludes you from removing anything from the IO monad. I understand you can't remove data from the IO so maybe transform it:
val added: List[IO[Page]] = for(page <- pages) {
val granted = alreadyAccessible.flatMap((aa: List[Page]) => {
if (!aa.contains(page))
pageModel.grantAccess(roleLst.head.id, page.id) match { case Right(p) => p }
else null
})
} yield granted
this unfortunately does not work with the following error:
Error:(62, 7) ';' expected but 'yield' found.
} yield granted
I think because I am somehow mistreating the for comprehension syntax, I just don't understand why I cannot do what I'm doing.
I know there must be a straight forward solution to such a problem, so any input or advice is greatly appreciates. Thank you for your time in reading this!
granted is going to be an IO[List[Page]]. There's no particular point in having IO inside anything else unless you truly are going to treat the actions like values and reorder them/filter them etc.
val granted: IO[List[Page]] = for {
How do you compute it? Well, the first step is to execute alreadyAccessible to get the actual list. In fact, alreadyAccessible is misnamed. It is not the list of accessible pages; it is an action that gets the list of accessible pages. I would recommend you rename it getAlreadyAccessible.
alreadyAccessible <- getAlreadyAccessible
Then you filter pages with it
val required = pages.filterNot(alreadyAccessible.contains)
Now, I cannot decipher what you're doing to these pages. I'm just going to assume you have some kind of function grantAccess: Page => IO[Page]. If you map this function over required, you will get a List[IO[Page]], which is not desirable. Instead, we should traverse with grantAccess, which will produce a IO[List[Page]] that executes each IO[Page] and then assembles all the results into a List[Page].
granted <- required.traverse(grantAccess)
And we're done
} yield granted

OrientDB Match with an Edge Property

I have this graph:
Regione -Ha-> Deceduto -alGiornoDeceduti -> Data
and the alGiornoDeceduti edge has the property name. I am trying this query, but it is not working:
match {class:Regione, as:r} -Ha-> {class:Deceduto, as:d} .outE("alGiornoDeceduti"){where:(name=r.name)}.inV() {class:Data, as:dd, where:(data="2020-05-03 00:00:00")} return r.name,d.deceduti,dd.data
I think the error is this:
{where:(name=r.name)}
because if I replace the r.name with for example 'Sardinia' it works.
You can refer to other nodes in the pattern using the $matched keyword, eg.
name = $matched.r.name

Titan: has() doesn't work

I have been trying to query my graph using this query
graph()
.traversal()
.V()
.has(Tokens.FIRSTNAME)
.filter(vt ->
vt.get().property(Tokens.FIRSTNAME).equals("Hank")
);
And that always return no result. When I debugged the code, I noticed that the comparison happens at AbstractElement#equals() and it returns false because the passed value (String) is not Vertex or Edge or VertexProperty
Another way to do the same thing but never works too is
graph()
.traversal()
.V()
.has(Tokens.FIRSTNAME, "Hank")
I'm using titan 0.9.0-M2
Am I doing something wrong?
The query should be:
graph()
.traversal()
.V()
.has(Tokens.FIRSTNAME)
.filter(vt ->
vt.get().value(Tokens.FIRSTNAME).equals("Hank")
);
Or even better:
graph()
.traversal()
.V()
.has(Tokens.FIRSTNAME, "Hank")