neo4j Parent child relationship of n-levels - cypher

I have Parent child relationships of say 10-11 levels like shown below and I need to create a relationship between them as parent child
data format
id,parentid
1,0
2,1
3,2
4,3
5,4
6,5
what I tried so far?
I have used the below code to relate them as parent child
LOAD CSV WITH HEADERS FROM 'file:///parent_child.csv' AS line
MERGE (thisThingHere:employee {id: line.id })
MERGE (parent:Element { id: line.parentid })
MERGE (thisThingHere)-[:PARENT]->(parent)
the result of above code is creating parent child relations but they are relating up to just one level, like shown in the below image (available as a link), I need a way to relate them and display it like a tree eg. 3 is a parent of 4 and 2 is a grand parent of 4 and 1 is great grand parent of 1, can anyone please help me on how can I achieve it?
result of my query above

You need to use the same node label for both parent and child node to construct a tree
LOAD CSV WITH HEADERS FROM 'file:///parent_child.csv'
AS line
MERGE (thisThingHere:Element {id: line.id })
MERGE (parent:Element { id: line.parentid })
MERGE (thisThingHere)-[:PARENT]->(parent)

Related

How to retrieve recursive childs on TypeORM

I've been experiencing some troubles lately trying to figure out a way to load recursively the childs of an entity on TypeORM (v0.3.10 on the moment I asked this question).
Right now, my objective is finding recursively all the childs from a given parentId (itself included).
For example:
Id
ParentId
1
NULL
2
1
3
2
4
NULL
Calling ID=1 should return [1, 2, 3], since the ID itself shall be included, 2 is child of 1 and 3 is child of 2.
Calling ID=2 should return [2, 3], since the ID itself shall be included and 3 is child of 2.
The entity itself looks like this at the moment:
#Entity(TableNamesConstants.GROUPS)
export class Group {
#PrimaryGeneratedColumn()
id: number;
#ManyToOne(() => Group, { nullable: true })
#JoinColumn({ name: 'parentId' })
parent?: Group;
#Column('int', { nullable: true })
parentId?: number;
}
I've tried several ways (Tree entities, trying to translate it from SQL to a TypeORM query following others suggestions, etc.) to no luck to achieve a N-depth query.
Can I have some guidance regarding this? Thanks in advance.

Why are all my SQL queries being duplicated 4 times for Django using "Prefetch_related" for nested MPTT children?

I have a Child MPTT model that has a ForeignKey to itself:
class Child(MPTTModel):
title = models.CharField(max_length=255)
parent = TreeForeignKey(
"self", on_delete=models.CASCADE, null=True, blank=True, related_name="children"
)
I have a recursive Serializer as I want to show all levels of children for any given Child:
class ChildrenSerializer(serializers.HyperlinkedModelSerializer):
url = HyperlinkedIdentityField(
view_name="app:children-detail", lookup_field="pk"
)
class Meta:
model = Child
fields = ("url", "title", "children")
def get_fields(self):
fields = super(ChildrenSerializer, self).get_fields()
fields["children"] = ChildrenSerializer(many=True)
return fields
I am trying to reduce the number of duplicate/similar queries made when accessing a Child's DetailView.
The view below works for a depth of 2 - however, the "depth" is not always known or static.
class ChildrenDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Child.objects.prefetch_related(
"children",
"children__children",
# A depth of 3 will additionally require "children__children__children",
# A depth of 4 will additionally require "children__children__children__children",
# etc.
)
serializer_class = ChildrenSerializer
lookup_field = "pk"
Note: If I don't use prefetch_related and simply set the queryset as Child.objects.all(), every SQL query is duplicated four times... which I have no idea why.
How do I leverage a Child's depth (i.e. the Child's MPTT level field) to optimize prefetching? Should I be overwriting the view's get_object and/or retrieve?
Does it even matter if I add a ridiculous number of depths to the prefetch? E.g. children__children__children__children__children__children__children__children? It doesn't seem to increase the number of queries for Children objects that don't require that level of depth.
Edit:
Hm, not sure why but when I try to serialize any Child's top parent (i.e. MPTT's get_root), it duplicates the SQL query four times???
class Child(MPTTModel):
...
#property
def top_parent(self):
return self.get_root()
class ChildrenSerializer(serializers.HyperlinkedModelSerializer):
...
top_parent = ParentSerializer()
fields = ("url", "title", "children", "top_parent")
Edit 2
Adding an arbitrary SerializerMethodField confirms it's being queried four times... for some reason? e.g.
class ChildrenSerializer(serializers.HyperlinkedModelSerializer):
...
foo = serializers.SerializerMethodField()
def get_foo(self, obj):
print("bar")
return obj.get_root().title
This will print "bar" four times. The SQL query is also repeated four times according to django-debug-toolbar:
SELECT ••• FROM "app_child" WHERE ("app_child"."parent_id" IS NULL AND "app_child"."tree_id" = '7') LIMIT 21
4 similar queries. Duplicated 4 times.
Are you using DRF's browsable API? It initializes serializer 3 more times for HTML forms, in rest_framework.renderers.BrowsableAPIRenderer.get_context.
If you do the same request with, say, Postman, "bar" should get printed only once.

rails ancestry pagination

I've just followed the Railscast tutorial:
http://railscasts.com/episodes/262-trees-with-ancestry
Is it possible to paginate results from Ancestry which have been arranged?
eg: Given I have the following in my Message controller:
def index
#messages = Message.arrange(:order => :name)
end
Then how would I paginate this as it's going to result in a hash?
Update
I found that if I use .keys then it will paginate, but only the top level not the children.
Message.scoped.arrange(:order => :name).keys
Update
Each message has a code and some content. I can have nested messages
Suppose I have
code - name
1 - Test1
1 - test1 sub1
2 - test1 sub2
2 - Test2
1 - test2 sub1
2 - test2 sub2
3 - test2 sub3
This is how I want to display the listing, but I also want to paginate this sorted tree.
It is possible but I've only managed to do it using two database trips.
The main issue stems from not being able to set limits on a node's children, which leads to either a node's children being truncated or children being orphaned on subsequent pages.
An example:
id: 105, Ancestry: Null
id: 117, Ancestry: 105
id: 118, Ancestry: 105/117
id: 119, Ancestry: 105/117/118
A LIMIT 0,3 (for the sake of the example above) would return the first three records, which will render all but id:119. The subsequent LIMIT 3,3 will return id: 119 which will not render correctly as its parents are not present.
One solution I've employed is using two queries:
The first returns root nodes only. These can be sorted and it is this query that is paginated.
A second query is issued, based on the first, which returns all children of the paginated parents. You should be able to sort children per level.
In my case, I have a Post model (which has_ancestry) . Each post can have any level of replies. Also a post object has a replies count which is a cache counter for its immediate children.
In the controller:
roots = #topic.posts.roots_only.paginate :page => params[:page]
#posts = Post.fetch_children_for_roots(#topic, roots)
In the Post model:
named_scope :roots_only, :conditions => 'posts.ancestry is null'
def self.fetch_children_for_roots(postable, roots)
unless roots.blank?
condition = roots.select{|r|r.replies_count > 0}.collect{|r| "(ancestry like '#{r.id}%')"}.join(' or ')
unless condition.blank?
children = postable.posts.scoped(:from => 'posts FORCE INDEX (index_posts_on_ancestry)', :conditions => condition).all
roots.concat children
end
end
roots
end
Some notes:
MySQL will stop using the ancestry column index if multiple LIKE statements are used. The FORCE INDEX forces mySQL to use the index and prevents a full table scan
LIKE statements are only built for nodes with direct children, so that replies_count column came in handy
What the class method does is appends children to root, which is a WillPaginate::Collection
Finally, these can be managed in your view:
=will_paginate #posts
-Post.arrange_nodes(#posts).each do |post, replies|
=do stuff here
The key method here is arrange_nodes which is mixed in from the ancestry plugin and into your model. This basically takes a sorted Array of nodes and returns a sorted and hierarchical Hash.
I appreciate that this method does not directly address your question but I hope that the same method, with tweaks, can be applied for your case.
There is probably a more elegant way of doing this but overall I'm happy with the solution (until a better one comes along).

Nhibernate partial eager load of child collection

If I have a parent object (Parent) which has a List(Of Child) objects as a many-one relationship. Is it possible to return a Parent with a subset of it's child objects (eagerly loaded)? I am using VB and Criteria.
e.g. If Parent 1 has 50 children (20 type X 30 type Y) and I want to return the Parent with a collection containing only type X.
I only want a collection with a size of 20 with it's eagerly loaded children?
Thanks
HQL query. The fetch keyword will initialize the children along with the parent.
from parent left join fetch parent.Children as child where child.type = X

How are nested set models traversed in MySQL?

I'm reading this article
and on the part with the query:
SELECT node.name
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.name = 'ELECTRONICS'
ORDER BY node.lft;
I'm wondering how is it travered? What happens step by step? I'm confused, please help.
Well, the database system could execute the query several different ways with the same result, but here's one way to understand what's going on:
Take 2 copies of the nested_category table, one named parent and the other named node. Find the row in parent named ELECTRONICS (the article you link to implies there's only one). The range parent.lft to parent.rgt gives any nodes with ELECTRONICS as an ancestor in the tree, at any depth.
Sorting by node.lft means you'll get the sub-nodes of ELECTRONICS along the left side of the sub-tree first, in an pre-order traversal.
It might be easier to walk through a simpler example to understand this: what if we choose TELEVISIONS instead of ELECTRONICS as the parent:
The 'parent' set has only 1 row, because of [parent.name = 'TELEVISIONS']:
{ name: "TELEVISIONS", lft: 2, rgt: 9 }
The 'node' set has the 4 rows that satisfy [node.lft between 2 and 9] because we can substitute the single lft/rgt values from parent:
{ name: "TELEVISIONS", lft: 2, rgt: 9 }
{ name: "TUBE", lft: 3, rgt: 4 }
{ name: "LCD", lft: 5, rgt: 6 }
{ name: "PLASMA", lft: 7, rgt: 8 }
And, as you can see, the above 4 rows are alread sorted by "lft" values, so to satisfy the query, we just take the name values and we're done.