For clarity purpose, step names are used as identifiers
I have the following Directed Acyclic Graph (DAG):
What I'm trying to do is select a node, and find all the other nodes that are not connected directly to the selected one, only in an outbound direction.
For example: if I select "root step", my query should only return "test step 3", since it is the only one not connected directly to "root step".
However, if I select "test step 2", it should only return "test step 3", and not "test step", because "test step* is at the same level that "test step 2" is.
For now, here is how I do:
I store, in every "step", the list of parents it has as an array. (test step has ["root step"], etc.)
My query is as follows ( for test step 2 as an example ):
FOR v, e IN 0..10 OUTBOUND "steps/test step 2" steps_relations
FILTER e._from != "steps/test step 2"
FILTER e._to != "steps/test step 2"
FILTER v._id != "steps/test step 2"
FILTER ["root step"] NONE IN v.parents
RETURN {id: v._key, name: v.name }
For now it returns an empty result instead of the expected ("test step 3"). Any help is greatly appreciated
I have finally managed to fix this. Here is how I did it:
first, I added two fields to each one of my "steps" document:
root: equals true when it is the root of the tree (like "root step"). Otherwise it simply references the internal ID of the root step
depth: equals to 0 for the root step, but is incremented. When I add a step to another, the new step's depth equals (parent + 1) ONLY if the result is bigger than the one actually stored.
Once I have this, my query looks as follows:
Situation: I want to list all the steps that can be linked to "test step 2"
FOR step, relation IN 0..10 ANY "steps/root step" steps_relations
FILTER step.depth > 1 /* THE DEPTH OF test step 2 WICH IS 1 */
FILTER relation._from != "steps/test step 2"
RETURN item
This returns successfully "test step 3"
You should rather use the min attribute to suppress edges directly connected:
FOR v, e IN 2..10 OUTBOUND "steps/test step 2" steps_relations
RETURN {id: v._key, name: v.name }
this way you will only get paths longer than one edge-hop, and the vertices from 2 onwards.
Related
I'm making a HTTP request to a REST API I created which contains two tables in the DBMS, the main table is called Levels looks like this
Levels:
leve_id: 1
level: "Level 1"
I have a child table called Units that looks like this
Units:
primary_id: 1
unit: "Unit 1"
unit_id: 1 ,foreign key to level_id
I have inserted "unit 1" and "unit 2" to this table and they both have the unit_id: equal to 1 because I want them in Level 1.
Now, the problem is when I'm trying to use a forEach loop in swiftUI to show the units.
struct UnitView: View {
#StateObject var unitVm = UnitViewModel()
var body: some View {
List(unitVm.units, id:\.idUnit){ unit in
Text(unit.unit)
}
}
}
It gives me an error of "ID 1 occurs multiple times"
Which is understandable since the foreign keys aren't unique,
could anyone point me in the right direction to show multiple units with the same id in a particular level?
It's a bit unclear what data you're working with, exactly, in terms of the UnitViewModel, but I'm guessing that it's a direct translation of the Units table, ie with four fields corresponding to: primary_id, unit, unit_id, and level_id.
For the purposes of the swiftUI List, it just needs each item to be uniquely identifiable (eg when you say scrollTo(someItemID)), so you should just supply it the path to your primary_id (which I assume is unique for the whole table) and all should work well. It won't care about the duplicates in idUnit, at that point.
I have a dataset which contains one column for task (e.g. task 1, task 2, task3). These task are repeated in the column as they have sub tasks mapped to them in another column. As well as status of each sub task (ready and not ready). I need a graph that can show me overall status of task 1, task2 and task3. If one of the sub task in task1 is not ready, the graph shows that the entire task1 is not ready and if all sub tasks are ready, the graph shows that the task1 is ready.
An example of the table is below
Your example is missing from your question.
From the sound of it you need a calculated column along the lines of:
Top Level task status =
Var topLevelTask = [MyTable]'Task'
RETURN IF (CALCULATE(COUNTROWS([MyTable]),
FILTER(ALL([MyTable]), [MyTable]'Task' = topLevelTask
&& [MyTable]'SubTaskStatus' = "Not Ready")
> 0,
"Not Ready", "Ready")
I'm trying to copy a vertex node and retain it's relationships in ArangoDB. I'm getting a "access after data-modification" error (1579). It doesn't like it when I iterate over the source node's edges and insert an edge copy within the loop. This makes sense but I'm struggling to figure out how to do what I'm wanting within a single transaction.
var query = arangojs.aqlQuery`
let tmpNode = (FOR v IN vertices FILTER v._id == ${nodeId} RETURN v)[0]
let nodeCopy = UNSET(tmpNode, '_id', '_key', '_rev')
let nodeCopyId = (INSERT nodeCopy IN 'vertices' RETURN NEW._id)[0]
FOR e IN GRAPH_EDGES('g', ${nodeId}, {'includeData': true, 'maxDepth': 1})
let tmpEdge = UNSET(e, '_id', '_key', '_rev')
let edgeCopy = MERGE(tmpEdge, {'_from': nodeCopyId})
INSERT edgeCopy IN 'edges'
`;
This quesion is somewhat similar to 'In AQL how to re-parent a vertex' - so let me explain this in a similar way.
One should use the ArangoDB 2.8 pattern matching traversals to solve this.
We will copy Alice to become Sally with similar relations:
let alice=DOCUMENT("persons/alice")
let newSally=UNSET(MERGE(alice, {_key: "sally", name: "Sally"}), '_id')
let r=(for v,e in 1..1 ANY alice GRAPH "knows_graph"
LET me = UNSET(e, "_id", "_key", "_rev")
LET newEdge = (me._to == "persons/alice") ?
MERGE(me, {_to: "persons/sally"}) :
MERGE(me, {_from: "persons/sally"})
INSERT newEdge IN knows RETURN newEdge)
INSERT newSally IN persons RETURN newSally
We therefore first load Alice. We UNSET the properties ArangoDB should set on its own. We change the properties that have to be uniq to be uniq for Alice so we have a Sally afterwards.
Then we open a subquery to traverse ANY first level relations of Alice. In this subequery we want to copy the edges - e. We need to UNSET once more the document attributes that have to be autogenerated by ArangoDB. We need to find out which side of _from and _to pointed to Alice and relocate it to Sally.
The final insert of Sally has to be outside of the subquery, else this statement will attempt to insert one Sally per edge we traverse. We can't insert Saly in front of the query as you already found out - no subsequent fetches are allowed after the insert.
How would you model the places visited by 2 or more people on a given date? Seems like it should be pretty simple but I don't get how to relate them to be able to say, User 1 and User 2 visited X on y date or how to say they visited X together on the same date.
I started this GraphViz to help visualise it:
digraph visit_example {
node [shape = doublecircle]; "User 1" "User 2";
node [shape = circle];
"User 1" -> Alaska [ label = "Visits" ];
"User 2" -> Alaska [ label = "Visits" ];
"Jan 1st" -> Date [label = "is a"];
"Mar 7th" -> Date [label = "is a"];
"Dec 9th" -> Date [label = "is a"];
}
How would you change the above to say, User 1 visited Alaska on March 7th with User 2? Independently, User 1 visited Alaska on Jan1st and User 2 on Dec 9th?
The advantage (and sometimes inconvenient) of a graph database is that such use cases can be modeled in multiple fashions.
It depends also on what kind of queries you would want to do.
Let's say, you'll never query by time and if you would do, query time is not important, you can easily put the date on the relationship property.
(a:User)-[:VISITED {time:0123456789}]->(p:Place)
If, you want to query by date, then you can for e.g., have a :Visit node representing the visit of the user and have a time property on it
(a:User)-[:DO_VISIT]->(v:Visit {time: 123456789})-[:IN_PLACE]->(p:Place)
Then you can query all :Visit nodes by time
Another solution is to manage a time tree, for e.g. GraphAware's TimeTree
Then your Visit node will be automatically attached to a TimeTree
(:Year {value:2015})-[:CHILD]->(:Month {value:7})-[:CHILD]->(:Day {value:8})<-[:EVENT_TIME]-(v:Visit)<-[:DO_VISIT]-(:User)
There are certainly other ways to model it, try the one that best fit your needs and performance of queries
I'm coming across some weird behavior in Drools 4.0.7, but maybe it's just cause I don't understand I how Drools works. Assume, there's a class "A" that has a property called "property".
As facts, I have the following list of A's:
A1, property = 123
A2, property = 345
A3, property = 123
I have two rules as follows:
rule "Rule 1 - Remove all A's that have property set to 123"
salience 1000
lock-on-active true
when
$listOfAs : ArrayList collect(A( property == "123" ))
then
for (Object a: $listOfAs ) {
retract (a)
}
end
rule "Rule 2 - Do stuff with remaining A's"
salience 900
lock-on-active true
when
$listOfAs : ArrayList collect(A())
then
...
end
My understanding is "Rule 1" will remove the facts of class A that have property to 123. When it gets to "Rule 2", shouldn't the "listOfAs" only have that one A that remains (i.e. the one where property is set to "345"). What I'm noticing is that "Rule 2" just doesn't execute at all even though I'm assuming there is still one "A" object that hasn't been retracted. If I comment out the "retract" it executes "Rule 2" fine.
Am I missing something about these rules work?
Thanks.
Justin
I suspect that the problem here is the use of 'lock-on-active'. Given that the first rule has activated, it prevents the other rule from also activating.
According to the docs lock-on-active is:
"A Boolean value. "true" inhibits additional activations of all rules with this flag set within the same ruleflow or agenda group."