I want to know if there is a way I can Query the full Graph in OrientDB with TRAVERSE * FROM V without getting the Edges as Objects. Because with the References in all the Objects I get more than 50MB data from a 10 Vertex Graph. I use the orientjs Driver.
My Data looks like this:
I used the Json-Stringify-Safe to convert the Json to a String.
You can use
select *,out.asString(),in.asString() from (traverse * from V) fetchplan [*] in_*:-2 out_*: -2
Hope it helps.
You can use this one to exclude the edges shown as records:
traverse * from V while #class NOT IN (select distinct(#class) from E)
BEFORE
AFTER
You can use this one to exclude the edges from each record but it will show you the edges as records:
select from (traverse * from V) fetchplan [*] in_*:-2 out_*: -2
And this is the mix of both queries:
select from (traverse * from V while #class NOT IN (select distinct(#class) from E)) fetchplan [*] in_*:-2 out_*: -2
Hope it helps
Related
does anyone know how to introduce wildcards (e.g. %% ) when querying a jsonb column that in this case is an array at the top level ? would also like to ignore casee
select * from "food" where (type #> '"xyz"')
You need to unnest the array:
select f.*
from food f
where exists (select *
from jsonb_array_elements_text(f.type) as x(typ)
where x.typ like '%xyz%');
One option would be applying a CROSS JOIN between the table and unnested array elements without a subquery as
SELECT j.*
FROM food f
CROSS JOIN jsonb_array_elements(type) AS j
WHERE value::text like '%"xyz"%'
Demo
thanks folks.. this seems to do the trick:
SELECT *
FROM
food,
jsonb_array_elements(type) as types
WHERE types::text ilike '%xyz%';```
Let's say I have the following list of vertices (connected by edges) in the orient database:
[t=1] --> [t=2] --> [t=3] --> [t=4] --> [t=5] --> [t=6] --> [t=7]
Each vertex has a timestamp t. I now want to receive the last vertex before a given date. Example: give me the last vertex before t=5, which is t=4.
Currently I'am using the following query to do this:
SELECT FROM ANYVERTEX WHERE t < 5 ORDER BY t DESC LIMIT 1
This is working fine when having up to let's say 1000 elements but the performance of that query drops with the number of elements inserted in the list. I already tried using an index, which improved the overall performance, but the problem, that the performance drops with the amount of elements still persists.
When building queries, always try to use the information you have about the relationship in your query to improve performance. In this case you don't need the sort (which is an expensive operation) because you know that the vertex you need has an incoming edge to the vertex, you can simply use that information in your query.
For example, let's say I have the following setup:
CREATE CLASS T EXTENDS V
CREATE VERTEX T SET t = 1
CREATE VERTEX T SET t = 2
CREATE VERTEX T SET t = 3
CREATE VERTEX T SET t = 4
CREATE VERTEX T SET t = 5
CREATE CLASS link EXTENDS E
CREATE EDGE link FROM (SELECT * FROM T WHERE t = 1) TO (SELECT * FROM T WHERE t = 2)
CREATE EDGE link FROM (SELECT * FROM T WHERE t = 2) TO (SELECT * FROM T WHERE t = 3)
CREATE EDGE link FROM (SELECT * FROM T WHERE t = 3) TO (SELECT * FROM T WHERE t = 4)
CREATE EDGE link FROM (SELECT * FROM T WHERE t = 4) TO (SELECT * FROM T WHERE t = 5)
Then I can select the vertex before any T as such:
SELECT expand(in('link')) FROM T WHERE t = 2
This query does the following:
Select the vertex from T where t=2
From that vertex, traverse the incoming edge(s) of type link
expand() the vertex from which that edge comes from to get all of its information
The result is exactly what you want:
This should give better performance (especially if you add an index on the attribute t of the vertices) because you are using all the information you know in advance about the relationship = the node you need has an edge to the node you select.
Hope that helps you out.
I want to get just radius value from ST_MinimumBoungingRadius.
Something like this (from postgresql documentation) works just fine:
SELECT radius
FROM
ST_MinimumBoundingRadius('MULTIPOINT(1 2,3 8,5 6)')
So I don't understand, why doesn't work similar query on existing table:
SELECT radius
FROM
(SELECT
ST_MinimumBoundingRadius(ST_Collect(geom)) minrad
FROM a) b
Result of this query is ERROR: column "radius" does not exist
Is there any way to extract just radius value?
The main difference is that in the first case you are calling the function in the FROM clause while in the second it is in the select clause. In the first case, the result is made of two column while in the later it is a string aggregation of all columns.
You can fix it by using the function in the FROM clause again, using either a double-parenthesis or a lateral join:
SELECT radius
FROM ST_MinimumBoundingRadius((SELECT ST_Collect(geom)
FROM a)) minrad;
or
SELECT radius
FROM (SELECT ST_Collect(geom) geom FROM a) tbla,
LATERAL ST_MinimumBoundingRadius(tbla.geom) minrad;
I'm trying to find the pairs of vertices that have the greatest number of common vertices between them. It is very similar to the 'number of mutual friends' example used in many graph database demos. I can determine the number of mutual vertices between a pair of known vertices using this:
SELECT Expand($query) LET
$query1 = (SELECT Expand(outE().in) FROM #1:2,
$query2 = (SELECT Expand(OutE().in) FROM #1:3,
$query = Intersect($query1,$query2);
The Count() of the above query's result is the number of common vertices.
However, I can't figure out how to aggregate that query across my entire data set. My best solution has been a brute force, where I iterate through each vertex and run the above query against all other vertices (technically, I do all the vertices 'after' that vertex).
My solution is inefficient and had to be coded in C# rather than done entirely in SQL. How can this be done using OrientDb's SQL?
You can use a SELECT with a MATCH:
SELECT FROM (
SELECT a, b, count(friend) as nFriends from (
MATCH
{class:Person, as:a} -FriendOf- {as:friend} -FriendOf-{as:b, where:($matched.a != $currentMatch)}
RETURN a, b, friend
)
) ORDER BY nFriends
Slight modification to #Luigi's answer:
SELECT a, b, Count(friend) AS nFriends FROM (
MATCH
{class:Person, as:a} -E- {as:friend} -E- {class:Person, as:b, where:($matched.a != $currentMatch)}
RETURN a, b, friend
) GROUP BY a, b ORDER BY nFriends DESC
I needed the GROUP BY or I just get one big count.
I haven't been able to find an answer for the SQL for this.
Given pairs of vertices (record ids) and edge types between them, I want to check if all pairs exists.
V1 --E1--> V2
V3 --E2--> V4
... and so on. The answer I want is true / false or something equivalent. ALL connections must be present in order to evaluate to true, so at least one edge (of correct type) must exist for each pair.
Pseudo, the question would be:
Does V1 have edge <E1EdgeType> to V2?
AND
Does V3 have edge <E2EdgeType> to V4?
AND
... and so on
Does anyone know what the orientDB SQL would be to achieve this?
UPDATE
I did already have one way of checking if one single edge exists between known vertices. It's perhaps not very pretty either, but it works:
SELECT FROM (
SELECT EXPAND(out('TestEdge')) FROM #12:0
) WHERE #rid=#12:1
This will return the destination record (#12:0) if an edge of type 'TestEdge' exists from #12:0 to #12:1. However, if I have two of those, how can I query for one single result for both queries. Something like:
SELECT <something with $c> LET
$a = (SELECT FROM (SELECT EXPAND(out('TestEdge')) FROM #12:0) WHERE #rid=#12:1)
$b = (SELECT FROM (SELECT EXPAND(out('AnotherTestEdge')) FROM #12:2) WHERE #rid=#12:3)
$c = <something that checks that both a and b yield results>
That's what I aim towards doing. Please tell me if I'm solving this the wrong way. I'm not even sure what the gain is to merge queries like this compared to just repeat queries.
Given a pair of vertices, say #11:0 and #12:0, the following query will effectively check whether there is an edge of type E from #11:0
to #12:0
select from (select #this, out(E) from #11:0 unwind out) where out = #12:0
----+------+-----+-----
# |#CLASS|this |out
----+------+-----+-----
0 |null |#11:0|#12:0
----+------+-----+-----
This is highly inelegant and I would encourage you to think about formulating an enhancement request accordingly at https://github.com/orientechnologies/orientdb/issues
One way to incorporate the boolean tests you have in mind is illustrated by the following:
select from
(select $a.size() as a, $b.size() as b
let a=(select count(*) as e from (select out(E) from #11:0 unwind out)
where out = #12:0),
b=(select count(*) as e from (select out(E) from #11:1 unwind out)
where out = #12:2))
where a > 0 and b > 0
Yes, inelegance again :-(
It might be useful to you the following query
SELECT eval('sum($a.size(),$b.size())==2') as existing_edges
let $a = ( SELECT from TestEdge where out = #12:0 and in = #12:1 limit 1),
$b = ( SELECT from AnotherTestEdge where out = #12:2 and in = #12:3 limit 1)
Hope it helps.