AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

TcxVirtualTreeList auf Datenebene filtern?

Ein Thema von Zacherl · begonnen am 28. Jul 2017 · letzter Beitrag vom 30. Jul 2017
Antwort Antwort
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

TcxVirtualTreeList auf Datenebene filtern?

  Alt 28. Jul 2017, 00:23
Hallo zusammen,

ich spiele grade ein wenig mit der TcxVirtualTreeList Komponente im "provider mode" mit aktiviertem "smart load" (Child-Nodes werden erst beim Aufklappen hinzugefügt). Hierzu habe ich mir eine Data-Source von TcxTreeListCustomDataSource abgeleitet und die erforderlichen Methoden implementiert. Klappt soweit auch alles wunderbar.

Nun möchte ich eine Filter-Funktion auf Datenebene einbauen, um nur Datensätze anzeigen zu lassen, die den Filterkriterien entsprechen. Das Problem an dieser Stelle ist, dass meine zugrundeliegende Datenstruktur die "tatsächlichen" Daten nur in den Blättern liegen hat, ich also zum Überprüfen des Filterkriteriums zwangsweise bis ganz ans Ende eines Asts traviersieren muss. Dieses Verfahren muss ich nun in den GetChildCount und GetChildRecordHandle Methoden der Data-Source implementieren.

Nehmen wir mal an, ich hätte folgende Struktur:
Code:
root
 | - child
       | - child
             | - data
       | - child
             | - data
Dann wird GetChildCount insgesamt 4x aufgerufen (theoretisch 6x, aber die Daten-Nodes können trivial 0 zurückgeben). Hierbei muss der Daten-Baum dann jeweils einmal vom entsprechenden Level aus bis zu den Blättern traversiert werden. Das ist schonmal unschön.

Noch problematischer wird es bei GetChildRecordHandle . Hier kann ich ja nun nicht mehr einfach auf Child[Index] zurückgreifen, sondern muss auch hier jedes Mal zwecks Überprüfung des Filterkriteriums bis zu den Blättern traversieren und dann den Index entsprechend umrechnen, so dass er die rausgefilterten Nodes ignoriert.

Hat hier jemand vielleicht eine performantere Lösung anzubieten? Caching ist natürlich eine Möglichkeit, wobei das bei großer Datenmenge doch schon ordentlich Speicher verbraten würde. Ich befürchte leider, das es aufgrund meiner Datenstruktur aber nicht anders machbar ist.

Viele Grüße
Zacherl
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#2

AW: TcxVirtualTreeList auf Datenebene filtern?

  Alt 29. Jul 2017, 10:40
Ich nutze zwar weder "TcxVirtualTreeList" noch "TcxTreeListCustomDataSource", habe dieses Grundsatzproblem aber selbst logisch wie folgt gelöst:

Mein "linearisierter Baum" arbeitet im GUI und bei der Nutzung stets voll virtuell, es gibt im Speicher eines Nodes nur temporär ChildNodes welche gerade angefragt werden
Es bei mir haben Nodes folgende Minimale Grundstruktur

//stored => so einfach "linear" in der DB-Table
- NodeID: eineindeutige UID, z.B. DB-AutoIncrement
- ParentID: NodeID des ParentNodes oder wenn ein "Root" gleich der eigenen NodeID
- Data1: beliebige Daten
- Data2: beliebige Daten
- Data3: beliebige Daten

//private => nur Temporär im Speicher
- RootPtr als schneller "BackLink"
- ChildIDs als NULL oder TList<NodeID>
- TimeStamp als 0 oder letztes Sync, einfach als "PrimitivCache".. wird mit immer mit dem "globalen" TimeStamp des Root verglichen, TimeStamp des Roots aktualisiert sich bei allen Move,Insert,Delete Operationen(aber nicht bei "DataChange" weil DataValues nie im Cache) wenn sich nicht der ChildSelbst um die Benachrichtigung(zur Aktualisierung) seines Parents kümmert, sodass das globale ungültig machen aller Caches so umgangen werden kann


Das Konzept stammt noch aus Zeiten von Delphi2007 32Bit, da war mir das mit 32Bytes per Node eine Löung um auch Millionen von Nodes als Records in einer simplen DB Struktur zu halten und effektiv per einfachstem SQL anzufordern oder gefiltert abzufragen
Code:
Abfrage aller RootNodes
select * from NodeTable where NodeID = ParentID

Abfrage aller RootNodes mit z.B. Filtervergelichswert :Data1
select * from NodeTable where NodeID = ParentID and Data1 = :Data1

Abfrage aller ChildNodes zu einer NodeID
select * from NodeTable where ParentID = :NodeID

Abfrage aller ChildNodes zu einer :NodeID mit z.B. Filtervergelichswert :Data1
select * from NodeTable where ParentID = :NodeID and Data1 = :Data1
Ich habe mir den SQL Kram je nach NodeDataTyp jeweils direkt in Getter&Setter und Setter der NodePropertys gebracht.. ein universelles ORM oder eine ganz sauberer eigener DB-VirtualTreeView/Node war nie mein Ziel, ich verwende dies auch heute oft noch als CodeTemplate per Copy&Paste und passe fix den Namen der Nodeklasse an und benenne sowie typisiere Data1.., dann nur noch passend auch das SQL dazu und gut is.

Zumindest wäre dein Ziel ein trotz Rekursivität möglichst effektives ZeitVerhalten auch bei Datenfiltern zu behalten aus meiner Erfahrung so durchaus gegeben, der Trick ist hier ja einfach die lineare Indexbasierte Suche und Datenhaltung hinter/neben dem TreeView

Ich denke, diese Grundlogik könnest du übernehmen und wirst die passenden Events oder Gett&Setter auch in "TcxVirtualTreeList..." finden.
Ersetze in deinen Gedanken einfach dein Child[Index] gegen ein Child[NodeID] was du bei passender DB-Struktur wie und wo auch immer stets einigermaßen deterministisch auswählen und nutzen kannst.


Sollte ich deine Fragestellung nach Suche und Select mit Filtermöglichkeit doch nicht richtig und für dich passend getroffen haben, dann liegt es eventuell daran, dass ich mich explizit nicht um die Frage Stellung "GetChildCount" & "GetChildRecordHandle" mit einem echt BaumBasierten Filter&Such Algo gekümmert habe, mich also die Baumtiefe bis zu den Blättern bei dieser Zugriffs&Filterlösung garnicht interessiert.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#3

AW: TcxVirtualTreeList auf Datenebene filtern?

  Alt 29. Jul 2017, 17:27
Vielen Dank für deine ausführliche Antwort

der Trick ist hier ja einfach die lineare Indexbasierte Suche und Datenhaltung hinter/neben dem TreeView
Das ist auf jeden Fall eine gute generelle Lösung für Probleme dieser Art. Auf meinen konkreten Fall kann ich das Prinzip leider nicht trivial übertragen, da meine Datenstruktur inkompatibel ist. Zwar habe ich auch eine lineare Grund-Datenbasis, aber im ersten Schritt wird aus diesen Daten ein Baum aufgezogen welcher ab diesem Zeitpunkt immer komplett im Speicher liegt (sind momentan ca. 7000 Datensätzen und werden in absehbarer Zeit auch keine signifikanten Mengen hinzukommen). Leider ist das Kalkulieren der Äste auch recht rechenaufwändig und muss nach Zielsetzungs zwangsweise dynamisch (basierend auf Grundlage der linearen Datenbasis) geschehen. Demzufolge befinden sich die Knoten nicht in der Datenbank und eine triviale Möglichkeit anhand der Daten auf die Anzahl und Relation der resultierenden Knoten zu schließen gibt es aufgrund der komplexen Berechnung auch nicht.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#4

AW: TcxVirtualTreeList auf Datenebene filtern?

  Alt 29. Jul 2017, 18:54
Ich würde in deinem Beispiel, wenn es nicht möglich ist, die 7000 Datensätze um zwei "CacheFelder für NodeID und ParentID" zu erweitern und beim einlesen nach deiner komplexen Baumstrukturberechnung das Ergebnis dieser entweder direkt zurück in die DB-Records geben, ober besser nach Berechnung eine JobTabelle als StrukturCache mit: Job(z.B. TimeStamp der Berechnung), RecordID(PK deines Datensatzes) und NodeID+ParentID anlegen. Ob nur im Speicher als wenn SQL fähiges MemTable oder einfach in der DB per Zusatztabelle(z.B. "TreeJobResult")

Dann behältst du dein "komplexes Struktur Konzept" so unverändert wie möglich bei, speicherst dir nur das Ergebnis deiner Berechnung(also die BaumStruktur) so minimalistisch wie möglich ohne Datenredundanz ab. Die GUI greift bei Filtereinsatz einfach über die wieder nun SQL fähig linearisierte SturkturInfo der Zwischenschicht auf die Ausgangsdaten zu.
Das ist bei 7000 Datensätzen sowohl vom Speicher als auch von der "zusätzlichen" Verarbeitungszeit pro Zugriff als auch beim pro Berechnung einmaligen erzeugen der "JobStruktur" völlig unkritisch.
(zufällig habe ich diese Schicht auch oft, denn das gleiche kann man mit den FilterErgebnissen so machen, so kann die GUI dem Anwender ganz simpel erlauben, mal zurück zum vorherigen Filter zu gehen, ohne das der nochmal berechnet werden muss... mit dem simplen Konzept eines im Prinzip globalen CacheTimeStamps bekomme ich zwar keinen optimal reduziertes Nachberechnungsschema hin, aber es ist garantiert das ich nie mit eventuell alter CacheStruktur arbeite, notfals berechnen sich alle Filter eben bei nochmaliger Verwendung sauber neu)

Geändert von mensch72 (29. Jul 2017 um 19:09 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: TcxVirtualTreeList auf Datenebene filtern?

  Alt 30. Jul 2017, 14:28
Ja ich denke so in der Art werde ich es wohl machen müssen Muss ich nur mal noch schauen, wie ich die Cache-Kohärenz gewährleisten kann, da die Daten auch zur Laufzeit geändert/ergänzt werden können. Mein Datenbaum stellt hierfür aber Events bereit, so dass das kein Problem sein sollte.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:30 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz