Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I use order_by? #804

Open
maksam07 opened this issue Nov 29, 2021 · 8 comments
Open

How do I use order_by? #804

maksam07 opened this issue Nov 29, 2021 · 8 comments

Comments

@maksam07
Copy link

Good afternoon. I want to sort the tree, but I understand that from some level the elements start to be displayed in the wrong level

obj = Model.objects.filter(level__lte=10).annotate(
    children_count=Count('children'),
    descendants_count=Floor((F('rght') - F('lft') - 1) / 2),
    comments_count=Count('comments'),
).order_by('tree_id', 'level', 'children_count', '-slug')

Tell me, can you somehow solve the sorting problem?

@matthiask
Copy link
Member

You could try running Model._tree_manager.rebuild() once. It could be that the MPTT attributes got out of sync. This can happen, unfortunately.

@maksam07
Copy link
Author

@matthiask I had such a function when I add new items. But this does not work, in the admin panel (with standard sorting) everything is displayed correctly, but on the site with my sorting it does not. It turns out that some children are not properly "attached" to their parents. And because of this, some parents seem to be empty, although in fact, children are simply not displayed on the desired parent.

@maksam07
Copy link
Author

maksam07 commented Dec 4, 2021

Without order_by

111

With order_by

222

@matthiask
Copy link
Member

I'm not sure what you want to achieve. The ordering doesn't look like either DFS or BFS at all. The "without order_by" example looks like a real tree. the "with order_by" example... I don't know. Is it expected that only the last children per level even have any descendants in turn? I'm confused.

@maksam07
Copy link
Author

maksam07 commented Dec 8, 2021

I'm not sure what you want to achieve. The ordering doesn't look like either DFS or BFS at all. The "without order_by" example looks like a real tree. the "with order_by" example... I don't know. Is it expected that only the last children per level even have any descendants in turn? I'm confused.

My point is that with sorting, children "go" to other parents. Parent "49" should have child "50" and that child should have child "52" and so on. But when sorting, it turns out that parent "49" has no children at all, and "50" the child passed to parent "23". This is just an example of connections. I cannot understand how to leave the children with their original parents, but at the same time sort the children according to a certain principle.
Next example: I need to sort comments by "rating". So that first I have the highest rated comments, then fewer, fewer, and even fewer. But if I again use a similar sorting, then already at the second level of comments, they will be displayed for other parents.

@matthiask
Copy link
Member

Ah, alright. Now I get it.

I'm not sure mptt is especially well suited for this, since the mptt attributes not only encode parent relationships but also ordering within siblings.

I'd try loading the tree into a Python datastructure and sorting it yourself in-memory (if the tree isn't too big) or else investigate whether adjacency lists and recursive common table expressions may be a better fit for what you're trying to achieve. If you're using PostgreSQL you could stuff the children count per node into an array and sort by this array, similar to what I'm doing with the tree_ordering here https://github.com/matthiask/django-tree-queries/blob/b6dd583fad6983533da984caab157096008fd38e/tree_queries/compiler.py#L63 . Of course you'd have to use a calculated value for this, not a model field.

@maksam07
Copy link
Author

maksam07 commented Dec 8, 2021

I'm not sure mptt is especially well suited for this, since the mptt attributes not only encode parent relationships but also ordering within siblings.

Perhaps you can suggest which tree building library would be better for me? I want to make comments like reddit. Can you advise something?

@matthiask
Copy link
Member

Here's a blogpost outlining what they did at Disqus (which is also based on Django):
https://cra.mr/2010/05/30/scaling-threaded-comments-on-django-at-disqus/

I linked my django-tree-queries library above. It cannot be used as-is because you have different ordering requirements but maybe you find something interesting there.

I wouldn't worry about performance too much for the time being; if you only have a few dozen comments per post you can just load everything into memory and to the sorting there (maybe even up to a few hundred comments... I don't know. There's no easy way around profiling/measuring your code.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants