$parent and $ current in orientDB query - orientdb

I read it on orientDB documentation but can't get a hold of it.
It would be great if someone could explain the use of $parent and $current in detail.
In a few examples I tried $parent.$parent.$current and $parent.$current, both give the same results which I feel should not happen. Below are my assumption:
$current gives access to the record/node currently being processed
$parent gives access to the parent of current record/node being processed

Your second assumption is wrong. It gives you access to the variables of the parent query (useful when calling traverse in a sub-query as stated here).
An example:
create class User extends V
create class Follows extends E
create vertex User set name = 'u1'
create vertex User set name = 'u2'
create vertex User set name = 'u3'
create edge Follows from (select from User where name = 'u1') to (select from User where name = 'u2')
create edge Follows from (select from User where name = 'u2') to (select from User where name = 'u3')
select $all from User
let $all = ( traverse out('Follows') from $parent.$current)

Related

Multipart column names in update statement with select

I'm sure this could be a duplicate but I can't seem to find the right search phrase.
Given a table in a named schema (i.e. not dbo) requires you include the schema name in the statement. So previously I'd have simply written it as so:
UPDATE [Schema].[Table1]
SET [AColumn] =
(
SELECT [SomeColumn]
FROM [Schema].[Table2]
WHERE [Schema].[Table2].[SameColumnName] = [Schema].[Table1].[SameColumnName]
);
But since More than two-part column name is deprecated, I need to find a new way to do this which is future proof. I have come up with 2 options, firstly using an alias:
UPDATE [Alias1]
SET [AColumn] =
(
SELECT [SomeColumn]
FROM [Schema].[Table2] [Alias2]
WHERE [Alias2].[SameColumnName] = [Alias1].[SameColumnName]
)
FROM [Schema].[Table1] [Alias1];
The second way is the one I'm really having trouble finding out if it's truly VALID T-Sql:
UPDATE [Schema].[Table1]
SET [AColumn] =
(
SELECT [SomeColumn]
FROM [Schema].[Table2]
WHERE [Table2].[SameColumnName] = [Table1].[SameColumnName]
);
I have tested both and they work, so my question is, is the second completely valid and normal to use just the table name without the Schema in this sense or should I rather opt for the slightly more verbose Alias?
As I said in my comment, alias your objects.
SELECT MT.MyColumn,
YT.MyColumn
FROM dbo.MyTable MT
JOIN so.YourTable YT ON MT.ID = YT.fID
WHERE YT.[name] = N'Jane';
If you're performing an UPDATE, then specify the alias of the object to Update:
UPDATE MT
SET MyColumn = YT.MyColumn --Column on the left side of the SET will always reference the table being updated
FROM dbo.MyTable MT
JOIN so.YourTable YT ON MT.ID = YT.fID
WHERE YT.[name] = N'Jane';

OrientDB select unique Vertices from multiple Edges

I have 2 vertices User and Stamp. Vertices are related by three edges Have, WishToHave and Selling.
I'm wish to select unique Stamps that have any relation with User. To do it I was running this command:
select expand(out('Have', 'WishToHave', 'Selling')) from #12:0
The problem with this command is that it returns 'Stamp1' few times, because it has Have and Selling edges.
How can I select all unique/distinct Stamps related to User1?
To init test data for this example:
create class User extends V
create class Stamp extends V
create class Have extends E
create class WishToHave extends E
create class Selling extends E
create vertex User set name = 'User1'
create vertex Stamp set name = 'Stamp1'
create vertex Stamp set name = 'Stamp2'
create vertex Stamp set name = 'Stamp3'
create edge Have from (select from User where name = 'User1') to (select from Stamp where name = 'Stamp1')
create edge WishToHave from (select from User where name = 'User1') to (select from Stamp where name = 'Stamp2')
create edge Selling from (select from User where name = 'User1') to (select from Stamp where name = 'Stamp1')
create edge Selling from (select from User where name = 'User1') to (select from Stamp where name = 'Stamp3')
I tried your case with your structure:
To retrieve unique vertices you could use the DISTINCT() function. I can give you two examples:
Query 1: Using EXPAND() in the target query
SELECT EXPAND(DISTINCT(#rid)) FROM (SELECT EXPAND(out('Have', 'WishToHave', 'Selling')) FROM #12:0)
Output:
Query 2: Using UNWIND in the target query
SELECT EXPAND(DISTINCT(out)) FROM (SELECT out('Have', 'WishToHave', 'Selling') FROM #12:0 UNWIND out)
Output:
Hope it helps

OrientDB graph database design: storing properties on edge vs nodes

I am using OrientDB to store information about video rentals. I represent members and movies as nodes. And whenever a member borrows a movie I add an edge between them. The dataset has user borrowing movie multiple times. Also I am required to store in which month/season (still deciding which will suit our needs but besides the point) was the movie rented. I was planning to store the above mentioned detail on the edge.But I came across this:
http://orientdb.com/docs/2.1/Performance-Tuning-Graph.html
And it is recommended to avoid storing properties on edges. I wanted to know whether I should change my approach ? If yes then what is the alternative?
Thanks in advance.
I think in your case you might opt for the creation of property directly on the edge. The alternative to store data related to rental is to create a third node (ex. RentalData) between Member and Movies and utilize PK and FK fields, but it would be similar to the relational DB and not necessary.
I reproduced a small DB:
create class Member extends V;
create property Member.id integer;
create property Member.name string;
create property Member.surname string;
create index Member.id unique;
create class Movie extends V;
create property Movie.id integer;
create property Movie.title string;
create property Movie.minutes integer;
create index Movie.id unique;
create class borrows extends E;
create property borrows.rentaldate Datetime;
create vertex Member set id = 1, name = "Paul", surname = "Green";
create vertex Member set id = 2, name = "John", surname = "Smith";
create vertex Member set id = 3, name = "Frank", surname = "Redding";
create vertex Movie set id = 1, title = "Interstellar", minutes = 170;
create vertex Movie set id = 2, title = "The Gladiator", minutes = 176;
create edge borrows from (select from Member where id = 1) to (select from Movie where id = 1) set rentaldate = sysdate();
create edge borrows from (select from Member where id = 1) to (select from Movie where id = 2) set rentaldate = sysdate();
create edge borrows from (select from Member where id = 2) to (select from Movie where id = 2) set rentaldate = sysdate();
create edge borrows from (select from Member where id = 3) to (select from Movie where id = 1) set rentaldate = sysdate();
create edge borrows from (select from Member where id = 3) to (select from Movie where id = 2) set rentaldate = sysdate();
I stored the "rentaldata" property directly on the edge "borrows" to associate the member to the movie borrowed and I think you could do it like me.
From the very same link you provided:
Use the schema
Starting from OrientDB 2.0, if fields are declared in the schema,
field names are not stored in document/vertex/edge themselves. This
improves performance and saves a lot of space on disk.
source

OrientDB: Is it possible to create a vertex together with an edge in one command?

I've got three classes:
Users extends V
Links extends V
Edges extends E
I have 3 Users, that won't usually change.
I have potentially 10000's of Links, and each one is connected to at least one of the Users (usually only one) via an Edge.
Is it possible to join these two commands, which are always called in succession, into one?
link = "insert into Links set title='Link 1'"
"create edge Edges
from ( select from Users where user_id='"+user_id+"')
to ( select from " + link._rid + ")"
That is some kind of pseudocode, I'm checking this out with pyorient.
Take a look at SQL Batch.
Your command(s) might look like the following...
pyorient_client.batch("""begin
let link = create vertex Links set name = 'Link 1'
let user = select from Users where user_id = '{}' lock record
let edge = create edge Edges from $user to $link
commit
return $edge""".format(user_id)
)

2 vertices connected two times with the same edge on lightweight mode

The orientdb documentation says regarding lightweight edges:
two vertices are connected by maximum 1 edge, so if you already have one edge between two vertices and you're creating a new edge between the same vertices, the second edge will be regular
Looking at the following script:
drop database plocal:../databases/test-lightweight admin admin;
create database plocal:../databases/test-lightweight admin admin;
connect plocal:../databases/test-lightweight admin admin;
alter database custom useLightweightEdges=true;
// Vertices
CREATE class Driver extends V;
CREATE PROPERTY Driver.name STRING;
// Edges
CREATE class Knows extends E;
CREATE PROPERTY Knows.in LINK Driver MANDATORY=true;
CREATE PROPERTY Knows.out LINK Driver MANDATORY=true;
// DATA
CREATE VERTEX Driver SET name = 'Jochen';
CREATE VERTEX Driver SET name = 'Ronnie';
// Jochen and Ronnie are very good friends
CREATE EDGE Knows FROM (SELECT FROM Driver WHERE name = 'Jochen') to (SELECT FROM Driver WHERE name = 'Ronnie');
CREATE EDGE Knows FROM (SELECT FROM Driver WHERE name = 'Jochen') to (SELECT FROM Driver WHERE name = 'Ronnie');
SELECT expand(out()) FROM (SELECT FROM Driver WHERE name = 'Jochen'); // 2 times Ronnie
SELECT count(*) FROM Knows; // 0
I would expect the last count to return 1, but it returns 0.
When I execute the same script but disabling the lightweight mode the result is 2 (as expected).