SQL query - fetch last nodes from graph/tree - sql

I'm looking for help. I want to fetch the last node in the tree. Having a table and data in that table creates a tree structure like here:
Node 0
/ \
Node 1 Node 2
/ \ \
Node 3 Node 4 <-- Node 5 <--
/
Node 6 <--
Each node has an id and parentId. So Node1 has id: 1 and parentId: 0 that connects it with the upper node.
Node columns:
Id
parentId (upper node)
What I want:
So when I choose node 0, I want to "go down" and get back nodes 6, 4, and 5. And when I choose node 1 I want to fetch nodes 6 and 4. The last nodes of the structure. I don't want intermediate nodes.
I tried doing a common table expression, with .. as. But I get intermediate nodes and that's a mess in my case.
Jpa solution is also appreciated.
Thanks and good luck ;)

Considering the following JPA model :
#Entity
class Node {
#Id
long id;
#ManyToOne
Node parent;
}
The leaves of the tree are the nodes not being a parent node.
If all the nodes of your model belongs to the same unique tree, the following request can be done :
SELECT n FROM Node n WHERE n NOT IN (SELECT p FROM Node p WHERE p.parent = n)
If you store several trees in your db or if you want the leaves under a specific node there is no way to build a recursive JPA query.
However, if there is not too much data in your Db, you can load all leaves (whatever node they belong to) with the same JPA request, and recursively scan each node in memory keeping those whose ancestor is the specific node limiting your scope.
BTW, if your store severeal trees in your Db, modifying the initial JPA model helps loading all the nodes of a tree with one JPA request.
Then do all kind of search in memory.
The model must be extended by adding on each node a relation to the root node :
#Entity
class Node {
#Id
long id;
#ManyToOne
Node parent;
#ManyToOne
Node root;
}
With such a model, the complete set of nodes of a tree can be loaded with one request :
SELECT n FROM node WHERE p.root.id = :id_of_the_wanted_root

Related

match, iterate, create and create relationship assistance

Using this pseudo code, how can I do this entirely in cypher?
match-all nodes with the property of type: Images
using properties from the original match
match using the properties from the main match for type: Parent nodes
if no nodes of the parameters with the type: Parent
create a new node using the parameters and type: Parent
match using the properties from the main match for type: Parent nodes
create a parent -> image relationship, using the node from the initial match and the match for type: Parent node

Ignite CacheQuery based on parent child index

Using ignite 2.9.x
I have two BinaryObject caches with one serves as a parent and the other as a child with an affinity key to the parent, this way I can colocate all relevant records on the same node.
I then want to select all child records based on the parent key. At the moment based on a 3 nodes cluster, the search time is linearly growing as I add new parent and child records (child records per parent is fixed (1000)).
I wonder if there is a way to add an index on the child cache parent property (asset) so the scan will scale more efficiently.
Production ..> Asset (asset)
can I define an index on the Production cache using the parent key asset?
what would this config look like?
How would the query change?
Should I use the AffinityKey in this case (how)?
IgniteCache<Integer, BinaryObject> productions = ignite.cache("productions").withKeepBinary();
Map<LocalDate, Double> totals = new HashMap<>();
try (QueryCursor<Cache.Entry<BinaryObject, BinaryObject>> cursor =
productions.query(
new ScanQuery<BinaryObject, BinaryObject>().setLocal(true).setFilter(this::apply))) {
for (Cache.Entry<BinaryObject, BinaryObject> entry : cursor) {
OffsetDateTime timestamp = entry.getValue().field("timestamp");
double productionMwh = entry.getValue().field("productionMwh");
totals.computeIfPresent(
timestamp.toLocalDate().withDayOfMonth(1),
(localDate, aDouble) -> aDouble + productionMwh);
totals.computeIfAbsent(
timestamp.toLocalDate().withDayOfMonth(1), localDate -> productionMwh);
}
}
private boolean apply(BinaryObject id, BinaryObject production) {
return key == ((Integer) production.field("asset"));
}
The only way to implement efficient parent->child link is to define SQL table and SQL index for your data. You can still collocate such data on affinity column.

Any way in Grails 3 for hasOne to do a lazy fetch?

Grails 3.2.5. Is see from my sql dump that the hasOne relationship does an eager fetch. This used to be the case back in prior versions of Grails, and the behavior could not be overridden. Is this still the case? What is the recommended model for a 1:1 relationship where we want a lazy fetch on the dependent object?
A little background. My "Comment" object has a one-to-one relationship with a "CommentText" object, where the text object holds Oracle clob text - some of it large. I only wanted to get the text when explicitly required to do so. The fk was in the dependent database text object, hence the "hasOne". Fortunately I was able to move the fk to the owner side of the association via an embedded domain object and update the db schema.
Throughout, I was unable to get lazy loading of the hasOne dependent object. Tried fetch: 'lazy'; fetchMode: 'lazy, and other variations of things. I needed a full domain class association because of "find" actions that needed to traverse the association.
I would still prefer the hasOne approach, if loading were indeed lazy.
Old question, but I just encountered the same problem so I'll answer for later reference.
Basically, it is impossible to lazy-fetch a hasOne property in Grails 3 (tested with 3.3.11, assuming Hibernate). But there are some workarounds.
The immediate lazy-fetch N+1 problem
As soon as you put hasOne: [child: Child] on the parent class, GORM will force you to make the relationship into a bidirectional one-to-one, and it will put the foreign key on the child table.
When you then fetch entities of the parent, it will immediately fetch all of the child entities as well, but it will do a query for every child (N+1 problem).
So a statement like this
Parent.list(max: 10)
will issue one query to get the 10 parents, and then do a query where parent_id = ? for each of the 10 children.
Even if you put fetch: 'lazy' and batchSize: 10 on the mapping of the child in Parent.groovy, the behavior is the same.
Workaround 1: One-directional with FK on the parent table
This is the solution you mention in your post. If you don't need to access the parent from the child side, you can make the relationship one-directional, which will put the FK on the parent table.
Now when fetching the Parent entity it will fetch the child_id from the parent table automatically, but keep the child property as a Hibernate proxy.
The child entity behind the proxy will correctly only be fetched once you access it. The batchSize mapping seems to be ignored here though, so when you actually start accessing the .child entities it will again issue one query per Parent.
Workaround 2: One-to-many and just access the first element
If you really want to keep the FK on the child table and also have lazy loading, you can use this hackaround.
On the Parent.groovy you could specify it like this
static hasMany = [children: Child]
static transients = ['child']
Child getChild() {
children ? children.first() : null
}
static mapping = {
children batchSize: 100
}
Now when you fetch the Parent entities it will correctly ignore the child property, and if you e.g. loop through a list of Parent and access the .child on each, it will only issue one single query for batchSize Parents.
So code like this:
def parents = Parent.list(max: 10)
parents.each {
log.info it.child.subProperty
}
will do the first query to get the 10 parents, and then one single query to lazily batch-fetch the children for up to batchSize parents. With Sql logging enabled it should look something like this:
select child0_.parent_id, child0_.id, ... from child child0_ where child0_.parent_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Workaround 3: The eager-fetch non-workaround
If your application code almost always uses the child property, then one option is to give up on lazy fetching and just specify child fetch: 'join' in Parent.groovy.
This will eliminate the N+1 lazy fetching problem, but as a downside Hibernate will now LEFT JOIN the child table and select all it's properties every time you request the Parent entity, even if you never touch the child property.
Workaround 4: Replace hasOne with mapping column: 'id'
class Face {
Nose nose // due to mapping, column 'nose_id' is not required
static mapping = {
nose column: 'id', insertable: false, updateable: false
}
}
class Nose {
static belongsTo = [face: Face] // due to mapping, column 'face_id' is not required
static mapping = {
// use the parent object's ID as this ID
// optional, but clean
id generator: 'foreign', params: [property: 'face']
// reference to the parent object so we don't need an extra column
face column: 'id', insertable: false, updateable: false
}
}

How to get Dynatree's parent node details

Is there any way to find dynatree's root node details? Supposed tree has 5 level and i selected fifth level's node . I want to get selected nodes and its parents details till root.
Thanks in advance.
The visitParents function on the node should do what you want:
node.visitParents(function (node) {
// do stuff with node
}, true);
Passing true as the second parameter includes the node as well as it's parents.
Try below method:
node.getKeyPath()
It should return string of keys from leaf to root node like below
/_3/_23/_26/_27
You should be then able to retrieve the any node details of that branch by parsing above string
var node = $("#tree").dynatree("getTree").getNodeByKey("3")
This might not be the exact solution but should give you the direction to get to your solution.
var parent = node.getParent();
var parentnode = parent.data.key;
In parentnode you will get the value of parent node.

NHibernate: Avoiding complete in-memory collections when working with child collections via aggregate root

Considering the simplified class below, lets assume:
that the parent can have a relatively large amount of children (e.g. 1000)
the child collection is lazy loaded
we have loaded one parent via it's Id from a standard Get method of a ParentRepository, and are now going to read the OldestChild property
class Parent
{
public IList<Child> Children { get; set; }
public Child OldestChild
{
get { return Children.OrderByDescending(c => c.Age).FirstOrDefault();
}
}
When using NHibernate and Repositories, is there some best practice approach to satisfy both:
a) Should select oldest child through the aggregate root (Parent) - [ie. without querying the children table independently via e.g. a ChildRepository using the Parent Id]
b) Should avoid loading the whole child collection into memory (ideally the oldest child query should be processed by the DB)
This seems something that should be both possible and easy, but I don't see an obvious way of achieving it. Probably I am missing something?
I'm using NHibernate 2.1, so a solution for that would be great, although will be upgrading to 3 soon.
I would create a specialized method on your repository, which returns the oldest child of a given parent.
You could map OldestChild using a Formula. Take a look at this to map a class to a formula: http://blog.khedan.com/2009/01/eager-loading-from-formula-in.html