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.
Related
I'm trying to create a new node with label C and relationships from a-->c and b-->c, but if and only if the whole pattern a-->c,b-->c does exist.
a and b already exist (merged before the rest of the query).
The below query is a portion of the query I want to write to accomplish this.
However, it creates a random empty node devoid of properties and labels and attaches the relationship to that node instead. This shouldn't be possible and is certainty not what I want. How do I stop that from happening?
merge (a: A {id: 1})
merge (b: B {id:1})
with *
call {with a, b
match (a)-[:is_required]->(dummy:C), (a)-[:is_required]->(b)
with count(*) as cnt
where cnt = 0
merge (temp: Temporary {id: 12948125})
merge (a)-[:is_required]->(temp)
return temp
}
return *
Thanks
I think there are a couple of problems here:
There are restrictions on how you can use variables introduced with WITH in a sub-query. This article helps to explain them https://neo4j.com/developer/kb/conditional-cypher-execution/
I think you may be expecting the WHERE to introduce conditional flow like IF does in other languages. WHERE is a filter (maybe FILTER would have been a better choice of keyword than WHERE). In this case you are filtering out 'cnt's where they are 0, but then never reference cnt again, so the merge (temp: Temporary {id: 12948125}) and merge (a)-[:is_required]->(temp) always get executed. The trouble is, due to the above restrictions on using variables inside sub-queries, the (a) node you are trying to reference doesn't exist, it's not the one in the outer query. Neo4j then just creates an empty node, with no properties or labels and links it to the :Temporary node - this is completely valid and why you are getting empty nodes.
This query should result in what you intend:
merge (a: A {id: 1})
merge (b: B {id:1})
with *
// Check if a is connected to b or :C (can't use a again otherwise we'd overwrite it)
optional match(x:A {id: 1}) where exists((a)-[:is_required]->(:C)) or exists((a)-[:is_required]->(b))
with *, count(x) as cnt
// use a case to 'fool' foreach into creating the extra :Temporary node required if a is not related to b or :C
foreach ( i in case when cnt = 0 then [1] else [] end |
merge (temp: Temporary {id: 12948125})
merge (a)-[:is_required]->(temp)
)
with *
// Fetch the :Temporary node if it was created
optional match (a)-[:is_required]->(t:Temporary)
return *
There are apoc procedures you could use to perform conditional query execution (they are mentioned in the linked article). You could also play around with looking for a path from (a) and check its length, rather than introduce a new MATCH and the variable x then checking for the existance of related nodes.
If anyone is having the same problem, the answer is that the Neo4j browser is display nonexistent nodes. The query executes fineā¦
I have created two models (A and B) with the same fields, only for backup purposes. I created a form with A as model using HTML Form Builder. Normally, form data will save in table A (model A). I want to save the data that is inserted in the B model as well.
If this models are identical just override the create and write and unlink method in A model to execute the same operation in B.
But for unlink and write I think you need to keep the id of model B in model A so when you delete a record from A you delete the corresponding record in b. nothing will confirm that the ids will be the sames.
#api.model
def create(self, vals):
a_id = super(YourClassName, self).create(vals)
b_id = self.env['B'].create(vals) # here no one will confirm that both have the same id
a_id.many2one_b_id = b_id # so you can execute write and unlink
return rec_id
#api.muli
def write(self,vals):
# don't forget using api.multi self can contain more than one record
# using mapped is better than looping through records and execute write
# one by one. and using api.one have the same effect
super(YourClassName, self).write(vals)
# using mapped will execute only one update queries for all ids
self.mapped('many2one_b_id').write(vals) # mapped will return the list of B record
return True
#api.multi
def unlink(self):
# same thing for delete
# delete B record first
self.mapped('many2one_b_id').unlink()
super(YourClassName, self).unlinck()
I have a graph which save topology of cloud infrastructure of a firm.It consists of Vertex called Object (Machines) and Edge called link (to denote how machines are linked to each other these links keep changing according as one machine can connect to different machines depending on need).
create class Object extends V
create class link extends E
Object vertices denotes Machine have properties to store config of the machine.
create property Object.ram long
create property Object.mem long
create property Object.cpu_core long
"link" edges links machine together to form a topology.It is a outbound edge from one machine to other. It has two time based property startTime which denotes the when this edge was created between two machines and endTime which initially is infinity and is update if we need to close this edge denoting that two machine and now no more linked.
create property link.startTime long
create property link.endTime long
create property link.l_id string
I want traverse from a Object(vertex) to all its connected Objects imposing a condition on link(edge) property while traversing that for a time say t, should be startTime <= t <= endTime.
For example Topology (Please click the link )
I want to traverse down from node rid #21:0 to all the edges using link edges whose startTime > 1488965393 and endTime < 1498965393. I am quite new to OrientDB and not able to figure out possible SQL command for the same.
Pseudo query (looking for something similar if possible):
SELECT * FROM (TRAVERSE out('link') FROM #21:0 while startTime > 1488965393 and endTime < 1498965393)
I was able to form a query that produced the desired output
SELECT id FORM (TRAVERSE out() FROM #21:0 WHILE (creationTime<= 1488965393 AND endTime >= 1488965393 AND #class='link')) WHERE #class= 'Object'
My use case is:
I have to return whole graph in result but the condition is
If there are more than 1 relationship in between two particular nodes in the same direction then I have to just merge it into 1 relationship. For ex: Lets say there are two nodes 'm' and 'n' and there are 3 relations in between these nodes say r1, r2, r3 (in the same direction) then when I get the result after firing cypher query I should get only 1 relation in between 'n' and 'm'.
I need to perform some operations on top of it like the resultant relation that we got from merging all the relations should contain the properties and their values that I want to retain. Actually I will retain all the properties of any one of the relations that are merging depending upon the timestamp field that is one of the properties in relation.
Note : I have same properties throughout all my relations (The number of properties and name of properties are same across all relations. Values may differ for sure)
Any help would be appreciated. Thanks in advance.
You mean something like this?
Delete all except the first
MATCH (a)-[r]->(b)
WITH a,b,type(r) as type, collect(r) as rels
FOREACH (r in rels[1..] | DELETE r)
Ordering by timestamp first
MATCH (a)-[r]->(b)
WITH a,r,b
ORDER BY r.timestamp DESC
WITH a,b,type(r) as type, collect(r) as rels
FOREACH (r in rels[1..] | DELETE r)
If you want to do all those operations virtually just on query results you'd do them in your programming language of choice.
I have a table called "Tag" which consists of an Id, Name and Description column.
Now lets say I have the tables Character (C), Movie (M), Series (S) etc..
And I want to be able to tag entries in C, M, S with multiple tags and one tag may be used for multiple entries.
So I could realize it like this:
T -> TC <- C
T -> TM <- M
T -> TS <- S
Where TC, TM, TS are the intermediate tables.
I was wondering if I could combine TC, TM, TS into one table with a type column added and still use foreign keys.
As of yet I haven't found a way to do it.
Or is this something I shouldn't be doing?
As the comments above suggested you can't combine multiple table into a single one. If you want to have a single view of the "tag relationships" you can pull the needed information into a View. This way, you only need to write a longer query once and are able to use like a single table. Keep in mind that you can't insert data into a view (there are possibilities to do so, but they are a little advanced)