OrientDB unique index on properties of two connected vertices - orientdb

I have two vertex classes V1 and V2, both have the property 'id'.
I have one edge class, E.
V1's id property is a unique index, so all V1 have unique ids.
Now I want that all V2 instances connected to a certain V1 instance have unique ids.
So:
OK (and needed to work)
V1(id:"A") ---- E ----> V2(id:"a")
V1(id:"A") ---- E ----> V2(id:"b")
V1(id:"B") ---- E ----> V2(id:"a")
V1(id:"B") ---- E ----> V2(id:"b")
Not OK
V1(id:"A") ---- E ----> V2(id:"a")
V1(id:"A") ---- E ----> V2(id:"a")
Preferably, as an addition, it should also be possible for V2 instances to exist without edges and they should then be unique in the global scope. If this last part is not possible, the first part is helpful anyways.
Is this possible by database configuration / indexing (on edge or vertices) or do I have to enforce it in the application?
UPDATE
What I mean with by configuration / indexing is that it would be prevented (exception) if you were trying to add the edge (just like when using a unique index to enforce that only one edge exists between two vertices).

I see only 2 ways to do this:
Put the V2 id attribute in the edge and call it v2id, so you can create an unique index against out + v2id
Create a hook (trigger) on onBeforeCreate() of class E and do your checks

You can use
update e set out=(select from v1 where id="a"), in=(select from v2 where id="a") upsert where out=(select from v1 where id="a") and in=(select from v2 where id="a")
Hope it helps.

Related

FK field over IPC

Some prerequisites on the remote process:
q)\p 15222
q)t:([id:10 20 30]data:`aa`bb`cc);
q)kt:([]id:`t$10 20 20 30 30 30; num:til 6);
and the following will be performed on a local process:
The size of kt looks the same from both sides:
q)-22!`::15222 "kt"
138
q)`::15222 "-22!kt"
138
But meta's are different:
q)`::15222 "meta kt"
c | t f a
---| -----
id | j t
num| j
q)meta `::15222 "kt"
c | t f a
---| -----
id | j
num| j
Why is it so? - why the transferred table does not contain a whole information as its source (despite of the sizes are the same)?
I suspect this somehow related to enums - q completely removes enum info - is it true?:
// remote
q)e:`a`b`c;
q)e1:`e$`b`a`c`c`a`b;
// local
q)`::15222 "type e1"
20h
q)type `::15222 "e1"
11h
Yes, enums (and thus foreign keys) aren't preserved when transported over IPC to another process.
Equal length from -22! doesn't mean identical content.
The reason for the difference between the two tables is because the enumeration domain isn't being sent over IPC so there is no guarantee that the enumeration domain exists in the local process or is the same as the remote process. If it were to send over the enumeration domain from the remote process then there's also the risk that it may overwrite a local enum domain in the local process.
Another point to note is that -22! checks the serialised size which will remove any foreign key on both client and server.
It might be worth checking out https://www.aquaq.co.uk/q/adventure-in-retrieving-memory-size-of-kdb-object/ for further reading on determining memory usage of kdb objects.

Get all relationships connected to a node that are NOT of a particular class

So you can easily get all connections to a vertex that are of a particular class by querying
select from Foo where both() in (#42:1)
This will get all the vertices of class Foo that are connected to vertex #42:1 with either outbound or inbound links.
However what would be the query if I wanted to get all the vertices that are connected to #42:1 that are not instances of class Foo?
Does OrientDB natively support this functionality or would I have to do something like an intersection?
why not using
SELECT * FROM (
... your select query
)
WHERE #class <> 'Foo'
Another way could be represented by using Matching Expression
MATCH
{E, where:(#class <> 'Foo')}-your_relation->{class:Foo}
RETURN E, F
Rob

How can I get the name of a table as a string in kdb+

e.g if table is tbl_trade_jan17, how can i get a string variable "tbl_trade_jan17"? I am afraid i might be missing something very obvious here!
The motive is not to use get or eval or call table from its name - functional.
The idea is to save the table on the hard disk with the same filename as the name of the table. Also to reference associated tables. e.g trd_jan17 might also have a quote_jan17 table and a sym_jan17 table associated. so if i can get the name tbl_trade_jan17, i can then get the names of associated tables by string manipulation.
EDIT: Question above changed
Correct me if I am wrong but it seems that you want to be able to call your table from the string "tbl_trade_jan17"?
In this case get and value are are interchangeable for this purpose.
q)tbl_trade_jan17:([]c:1 2 3;c2:1 2 3)
q)type tbl_trade_jan17 / tbl_trade_jan17 is a table (type 98h)
98h
q)/ to use the string as a variable to retrieve the table:
q)get "tbl_trade_jan17"
c c2
----
1 1
2 2
3 3
q)value "tbl_trade_jan17"
c c2
----
1 1
2 2
3 3
idea is to save the table on the hard disk with the same filename as the name of the table.
To get a list of tables defined, use tables
e.g.
tables`. //for the root name-space
you can filter with like
e.g.
t:tables`.
t:t where t like "pattern_*"
and then save with save
save each hsym t //careful
Use string function
q) string `tbl_trade_jan17
"tbl_trade_jan17"

Select and insert by keeping references to original data in OrientDB

I am exploring graphDB query languages. At the moment looking at OrientDB query language. I would like to see how a transaction would look like in OrientDB with the following structure:
Suppose, I have two vertices, A and QA:
CREATE CLASS A EXTENDS V
CREATE CLASS QA EXTENDS V
Class A has a property called p1 of Integer:
CREATE PROPERTY A.p1 integer
Assume that A has three records called a1,a2,a3 with their corresponding values for p1 are a1.p1=2; a2.p1=5; a3.p1=10;:
INSERT INTO A SET p1 = 2 // call this a1
Created record with RID #11:1
INSERT INTO A SET p1 = 5 // call this a2
Created record with RID #11:2
INSERT INTO A SET p1 = 10 // call this a3
Created record with RID #11:3
And assume that I have an edge called isA from QA to A.
CREATE CLASS isA EXTENDS E // it seems that I can not restrict isA records to connect only QA records to A
I would like to see how the following transaction would look like in OrientDB:
first: select all A's content where p1 < 6 => so I will get {a1,a2}
second: for each element in the first query create an element in QA => so I will get for example {qa1,qa2}
third: Add records to isA Edge such that they connect elements in QA to their corresponding elements in A; =>so, for example connect qa1 to a1 and qa2 to a2.
It seems all three queries are inter-related.
My 1th Question: how the above transaction (i.e., set of inter-related queries) would look like in OrientDB?
Note that elements of A are dynamic (not fixed during my system) and I would like to synch QA elements with A, whenever A's content changes by employing the above transaction; for example, if I add a4 to A with p1=3, and run the above set of queries, I am expecting to get a new record in QA, say qa4 which is linked to a4.

Cypher - WHERE and AND with 2 ids

I have a node with id 1 and a node with id 2 in the database and they are linked to each other. Why when I run this query
MATCH (a)-[r]-(b) WHERE id(a)=1 AND id(b)=2 RETURN *;
Nothing is returned?
Solution
I use GrapheneDB. Usually GrapheneDB presents the system node id on the node graphic but when you have an attribute id it presents that instead. When I ran the query I was using the graphic id which wasn't actually the system id so id(a) didn't give the expected result.
Because the WHERE clause is evaluated for each candidate result, and the entire clause must evaluate to true.
Also, putting MATCH (a)-[r]-(b) will only find parts of the graph where those two nodes are related.
If you just want to find nodes 1 and 2, you can do this:
MATCH n
WHERE id(n) = 1 OR id(n) = 2
RETURN n
However, you should not be using node ids. They are deprecated, and being phased out. There are lots of other ways to find and identify nodes that don't rely on their internal identifier. If you open a new question with your actual scenario, we could help you write a better query.