kostenloser Webspace werbefrei: lima-city


Abbildung SQLite in Dateisystem und umgekehrt

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    noxious

    Kostenloser Webspace von noxious

    noxious hat kostenlosen Webspace.

    Moin,

    ich habe ein kleines Projekt, wo ich größere SQLite3-Datenbanken mit entsprechenden Daten ausliefern möchte. Dabei möchte ich diverse Dinge in den SQLite-Tabellen speichern - von reinen INT oder TEXT-Feldern, bis hin zu BLOB-Elementen wie Bildern und ähnlichem.

    Nun stehe ich vor der Aufgabe, diese Felder zu füllen - und da sich die Daten nicht zwangsweise aus reinen Rohdaten zusammen stellen, sondern halt auch zum Beispiel Bilder darin vorkommen, welche vorher manuell erstellt/bearbeitet werden müssen, bietet es sich eigentlich an, diese in einem Dateisystem zu bearbeiten und unter entsprechenden Namenskonventionen dann in die Datenbank eintragen zu lassen. Diesen Vorgang wollte ich nun mehr oder weniger automatisieren.

    Das Problem ist, dass ich nicht nur die Inhalte, sondern auch die Tabellen-Struktur dynamisch anpassbar machen will. Kurzum: Aus dem Dateisystem soll später automatisiert heraus gelesen werden, wie die Tabelle heißt, welche Felder sie hat und wie diese zu verstehen sind. Für die einfacheren Dinge habe ich mir dann ein format ausgedacht wie
    ./tabellen_name/id/feldname.TEXT
    ./tabellen_name/id/feldname.INT
    ./tabellen_name/id/feldname.BLOB
    Und so weiter. Die Interpretation sähe dann in etwa aus wie
    ResourceFile * ResourceFile::interpretFileSystem(std::string path, std::string filename, TreeNode * parent)
    {
        for(const auto & table : std::filesystem::directory_iterator(path)){
            if(table.is_directory()){
                std::map<std::string, std::string> values;
                std::string table_name = table.path().filename();
                for(const auto & item : std::filesystem::directory_iterator(table.path())){
                    if(item.is_directory()){
                        std::string item_id = item.path().filename();
                        for(const auto & value : std::filesystem::directory_iterator(item.path())){
                            std::string data_type = "";
                            std::string data_name = "";
                            if(value.is_regular_file()){
                                std::string filename = value.path().filename();
                                if(filename.compare(filename.length() - 4, 4, "TEXT") == 0){
                                    data_type = "TEXT";
                                    data_name = filename.substr(0, filename.length() - 5);
                                    values.insert_or_assign(data_name, data_type);
                                }
                                /*
                                    [...]
                                */
                            }
                        }
                    }
                }
                std::string sql = "CREATE TABLE IF NOT EXISTS `" + table_name + "` ( `id` INT PRIMARY KEY NOT NULL";
                for(const auto &pair : values){
                    sql += ", `" + pair.first + "` " + pair.second;
                }
                sql += " );";
                // [...]
            } 
        }
        // [...]
    }
    Als ich damit anfing, fiel mir schnell auf, dass das ganze doch erhebliche Schwachstellen hat - wo beispielsweise das Dateisystem schnell mal mit der Namenskonvention kollidiert. Zum Beispiel stellen sich einige Bildeditoren wie GIMP ziemlich an, wenn es darum geht, Dateien mit veränderter Dateierweiterung richtig zu laden/speichern - es interpretiert Bilder offenbar anhand der Dateinamen-Erweiterung, was ich für ziemlich schräg halte, da der Dateiindikator aka "Magic Number" den Dateityp ja eigentlich ziemlich eindeutig bestimmen sollte.
    Kurzum: Schwergewichtige Workarounds schaffen oder das Konzept überarbeiten.

    Eine weitere Idee wäre gewesen, die Tabellen-Struktur in einer Datei im Wurzelverzeichnis einer jeden Datenbank festzulegen - was aber meiner Meinung nach keine zu bevorzugende Lösung ist, da man dann immer zwei Dateien editieren muss. Da könnte ich auch einfach die Datenbank in einem Datenbank-Editor(SQLite-Browser oder ähnlichem) öffnen und anpassen.

    Der letzte Weg wäre natürlich das Schreiben eines eigenen Editors - was ich aber wenn möglich vermeiden möchte.

    Habt ihr möglicherweise eine Idee oder Anregung, wie man damit umgehen kann? Hat jemand schon mal etwas ähnliches gemacht?

    PS: Sorry für den Code - der war eher so als "Proof of Concept", bzw. "Work in Progress" gedacht und ist deshalb weder kommentiert, noch wirklich gut oder sinnvoll strukturiert. Konstruktive Kritik nehme ich dennoch gerne entgegen. Der ganze Funktionsrumpf kann eigentlich ignoriert werden - Das ganze ist Teil der Klasse ResourceFile, der TreeNode-Pointer ist nur dafür da, weil das ganze später über eine zentrale Speicherverwaltung gemanaged wird und dadurch das ganze mit new und delete weg fällt. Also für den Fall unwichtig.

    Beitrag zuletzt geändert: 28.2.2020 14:45:04 von noxious
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Ich bin nicht ganz sicher ob dir das so überhaupt weiter hilft - aber schaden sollte es ja auch nicht :)

    Das ganze ist natürlich nur ne Überlegung wie man es anstellen könnte, ohne auf Performance oder Sinnhaftigkeit zu kucken.

    Da würde ich zum Speichern der Daten erstmal JSON bevorzugen - einfach weil man an die Keys innerhalb der Objekte problemlos wieder ran kommt und damit sehr flexibel Unterwegs ist.

    Man könnte den Aufbau auf zwei Arten dabei machen: entweder die Objekte verschachteln oder nur Referenzen über IDs legen. Ersteres hat den Nachteil das wir für die Nutzung nicht direkt das JSON Objekt verwenden können sondern nur das daraus erstellte eigene Objekt. Das wäre beim speichern oder beim ändern der Struktur nicht ganz so einfach wie als hätten wir nur Referenzen über IDs.

    Wenn man also nen JSON Objekt nehmen würde und diese untereinander nur über deren IDs verketten würde, könnte man damit sicher gut arbeiten.

    Das könnte zum Beispiel so aussehen (" entfernt):

    {id:long/string/uuid, parent:long/string/uuid, alias:string, isdir:bool, childs:[long/string/uuid], type:string, data:bytes_as_BASE64}


    id - ID des aktuellen Objekts
    parent - ID des parent Objekts (null = isroot)
    alias - sowas wie Dateiname
    isdir - legt fest ob es ein Verzeichnis oder eine Datei darstellt
    childs - array von untergeordneten Objekten (nur wenn isdir)
    type - information als Hilfestellung um Rauszufinden was dieses Objekt an Daten beinhaltet (nur wenn nicht isdir)
    data - eigentliche Daten in Base64 kodierten bytes (nur wenn nicht isdir)

    Dann müsste man beim Laden dieser Objekte vom Programm aus eine Funktionalität bereitstellen wie getData, getChilds, getParent etc; dass könnte mit ner Hashmap mit ID und dem Objekt sicherlich gut möglich sein.

    Eventuell würde man die Daten von der eigentlichen Struktur lösen und sie getrennt mit ID, Typ und Daten ablegen und diese nur bei Bedarf laden.

    Da die Struktur ja nicht wirklich komplex ist (und sich eigentlich auch nicht viel verschachtelt bis auf das eine Array) müsste sich das ganze doch ggf auch in einer SQL Tabelle anlegen lassen.

    Dafür würde ich die Daten (keys: id, type, data) in einer Tabelle und die Struktur mit dem Rest in einer anderen Tabelle ablegen.
    Dabei müsste eventuell (falls man nicht mit mehreren Werten in einem Feld arbeiten möchte) der Eintrag einfach mehrfach angelegt werden mit unterschiedlichen Child Werten.

    Also in etwa so sieht das dann in der Tabelle aus (braucht dann ja noch nen anderen Wert als unique):
    B und C sind Child von A

    Struktur:
    0 | A | B | isDir
    1 | A | C | isDir
    2 | B | # | isFile
    3 | C | # | idFile

    Daten
    0 | C | txt | X0RBVEVOXw==
    1 | C | txt | X0FOREVSRV9EQVRFTl8=


    Deine Anwendung müsste dann natürlich neben den Zugriffen und der Struktur-Verwaltung drum herum dafür sorgen das die Daten wieder in das richtige Format gebracht werden wenn du sie lesen musst, aber die Struktur der Datenbank müsste nicht dafür angepasst werden.

    Eventuell hilft dir das etwas weiter :)


    // Edit

    Das Problem ist, dass ich nicht nur die Inhalte, sondern auch die Tabellen-Struktur dynamisch anpassbar machen will. Kurzum: Aus dem Dateisystem soll später automatisiert heraus gelesen werden, wie die Tabelle heißt, welche Felder sie hat und wie diese zu verstehen sind.


    Oh das hatte ich ganz überlesen. warum sollte das ganze dynamisch funktionieren wenn ich fragen darf? Die Daten könnten doch in einem einheitlichen Format existieren und der Code drum rum würde die entsprechende Funktionalität bereitstellen. Vermutlich ist mir nicht ganz klar was genau du damit vor hast bzw was das ganze darstellen soll.

    Beitrag zuletzt geändert: 29.2.2020 0:02:28 von horstexplorer
  4. Autor dieses Themas

    noxious

    Kostenloser Webspace von noxious

    noxious hat kostenlosen Webspace.

    horstexplorer schrieb:
    Da würde ich zum Speichern der Daten erstmal JSON bevorzugen - einfach weil man an die Keys innerhalb der Objekte problemlos wieder ran kommt und damit sehr flexibel Unterwegs ist.
    JSON war die erste Idee, aber SQL bietet einfach Vorteile, die JSON nicht hat.So ist es beispielsweise vergleichsweise schwierig, Binärdaten in JSON abzulegen, ohne sie vorher in ein weniger effizientes Format wie base64 umzuwandeln. Des weiteren hat SQL schon diverse Search-Insert-Delete-Undsoweiter-Operationen implementiert, welche bei JSON im wesentlichen erst "neu erfunden" werden müssten. Zudem mag ich SQL.

    horstexplorer schrieb:
    Oh das hatte ich ganz überlesen. warum sollte das ganze dynamisch funktionieren wenn ich fragen darf? Die Daten könnten doch in einem einheitlichen Format existieren und der Code drum rum würde die entsprechende Funktionalität bereitstellen. Vermutlich ist mir nicht ganz klar was genau du damit vor hast bzw was das ganze darstellen soll.
    Natürlich darfst du fragen.
    Es geht hierbei nicht um einen "Enduser"-Prozess, sondern im wesentlichen um eine Komfort-Funktion, um mir das erstellen und bearbeiten der Daten für einen "Enduser"-Prozess zu erleichtern. (im wesentlichen ein mal im build prozess aufgerufen, also ein META-Programm) Es steht noch nicht fest, welche Daten vorhanden sind und welcher Art diese sind. Ich will nur recht zügigen Zugriff darauf, wenn ich diese Daten brauche, ohne jedes mal das Parsen von Dateien neu zu erfinden.
    Es soll im wesentlichen wie ein Notizblock sein: Man weiss noch nicht, ob man diese Daten braucht, aber man will dem Endprozess Zugriff darauf erlauben, falls man sie benötigt.
    Letztenendes kann man das ganze auch kindisch beantworten mit einem: Ichwillaber-ichwillaber-ichwillaber! *stampf*

  5. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Ah okay, also sollen die Daten möglichst bereits im richtigen Datentyp vorliegen.

    Würde sich da nicht eine noSQL DB eher eignen? (Vermutlich nein da das ganze portabel sein soll denke ich) Da wäre man ja nicht auf eine Struktur angewiesen sondern könnte für jedes Objekt diese einzeln festlegen.
    In SQL würde ich das in etwa so lösen:
    für jedes Datenobjekt
       alle Datentypen erhalten
       für jeden Datentyp überprüfen ob es eine Spalte in der Tabelle gibt - wenn nicht diese anlegen
       daten in tabelle ablegen

    Das würde aber dazu führen das, sagen wir wir haben 3 Objekte (A,B,C) mit den Datentypen X,Y,Z; Dann wäre ja immer dort eine Lücke wo ein Objekt einen Datentyp nicht hat.
    ID | Desc | X | Y | Z |
    0  | A    | 1 | - | - |
    1  | A    | 2 | - | - |
    2  | B    | - | 1 | - |
    3  | B    | - | - | 1 | 
    4  | C    | - | - | 1 |

    Vermutlich ist das kein Problem was die Performance an geht - beim lesen der Daten müsste man aber dann drauf achten das entsprechende Datentypen vorhanden sind.
    Da würde es sich eventuell eher anbieten das in mehrere Tabellen zu unterteilen - eine für jeden Datentyp. So lässt sich das ganze eventuell etwas geordneter nachvollziehen, besonders wenn bestimmte Objekte mehrere Datentypen haben oder mehrfach den selben.
    X]
    ID | Desc | D |
    0  | A    | 1 |
    1  | A    | 2 |
    
    Y]
    ID | Desc | D |
    0  | B    | 1 |
    
    Z]
    ID | Desc | D |
    0  | B    | 1 |
    1  | C    | 1 |


    Persönlich finde ich die Wahl mit der getrennten Tabelle etwas schöner - man könnte so bestimmten Nutzern verschiedene Rechte auf verschiedene Datentypen geben und hätte das ganze etwas sauberer getrennt. Das hätte aber den Nachteil das sich nicht ganz so schnell herausfinden lässt welchen und wie viele Datentype ein bestimmtes Objekt hat.
    Da wäre dann die Frage ob du weißt welche Daten du brauchst um eine bestimmte Aktion durchzuführen z.Bsp Bilder bearbeiten -> Bestimmter Dateityp -> Dateiname => gut mit mehreren Tabellen zu finden / Dateiname -> unbekannte Aktion -> was ist möglich/welche Daten sind vorhanden => besser mit einer Tabelle da sich das einfacher sortieren lässt

    Eventuell könnte man auch die Version mit der Aufteilung in Tabellen erweitern mit einer Tabelle um festzustellen welche Datentypen ein bestimmtes Objekt hat. Das würde dann allerdings mehr Verwaltung benötigen.

    Beitrag zuletzt geändert: 29.2.2020 17:55:12 von horstexplorer
  6. Autor dieses Themas

    noxious

    Kostenloser Webspace von noxious

    noxious hat kostenlosen Webspace.

    horstexplorer schrieb:
    Würde sich da nicht eine noSQL DB eher eignen? (Vermutlich nein da das ganze portabel sein soll denke ich) Da wäre man ja nicht auf eine Struktur angewiesen sondern könnte für jedes Objekt diese einzeln festlegen.
    Ich bin nicht sicher - da ich im Prinzip noch nie mit noSQL gearbeitet habe. Aber nachdem, was ich darüber in Erfahrung bringen konnte, hat noSQL grade bei größeren Datenmengen Performance-Probleme.
    Ich möchte hier noch mal anmerken, dass es sich hierbei um eine reine Datensammlung handelt, wo der schnelle Zugriff(Search&Select) auf die Daten wichtiger ist, als das Einfügen, da die Daten am Ende, wenn sie ein mal eingefügt sind, (in der Regel) nicht mehr bearbeitet werden - ich würde also aus Performance-Gründen eher dazu tendieren, die Daten von Hand in die Datenbank einzutragen, als dass ich im Endprodukt Performance-Einbrüche habe.
    Möglicherweise hast du dazu ja einen größeren Erfahrungsschatz, was die Performance-Probleme von noSQL angeht? Und welche Probleme bringt noSQL mit der portabilität mit sich?

    horstexplorer schrieb:
    In SQL würde ich das in etwa so lösen:
    Was ja im wesentlichen ein ähnlicher Ansatz ist, wie ich ihn verfolgte. Mein Ansatz war ja:
    1. Die Ordner im Zielbereich einlesen
    2. Für jeden Orner Eine Map<string,string> anlegen,
    3. Durch den Ordner der jeweiligen IDs iterieren
    4. Dateinamen zu Feldname und Datentyp parsen.
    5. wenn ein neuer Feldname "als Dateiname" existiert, wird dieser Feldname und der dazugehörige Datentyp in die Map eingefügt.(map<feldname, datentyp>)
    6. Aus der Map eine SQL-Abfrage erstellt, welche die Tabelle generiert
    7. Die Daten eintragen.

    Das Problem ergibt sich im wesentlichen bei Punkt 4 - das Parsen der Dateien in Feldname und Datentyp.

    horstexplorer schrieb:
    Das würde aber dazu führen das, sagen wir wir haben 3 Objekte (A,B,C) mit den Datentypen X,Y,Z; Dann wäre ja immer dort eine Lücke wo ein Objekt einen Datentyp nicht hat.
    Das ist im wesentlichen kein Problem - in einigen Fällen ist das sogar absehbar und so gewollt. Im Endprodukt wird selbstverständlich die Existenz und validität der Daten überprüft.

    horstexplorer schrieb:
    Persönlich finde ich die Wahl mit der getrennten Tabelle etwas schöner - man könnte so bestimmten Nutzern verschiedene Rechte auf verschiedene Datentypen geben und hätte das ganze etwas sauberer getrennt.
    Mehrbenutzer-Systeme spielen eigentlich keine Rolle. Ich benutze SQLite lediglich, um auf die recht mächtigen Search&Select--Funktionen zugriff zu haben und auf ein eigenes prorietäres Format zu verzichten - letzteres neben der offensichtlichen Zeitersparnis halt auch aus dem Grund, dass jeder die Daten auch außerhalb des Programms lesen können soll. Es wird keine Client/Server-Anwendung. Da würde sich SQL ja allgemein weniger anbieten, sondern ich würde auf eine REST-API oder ähnliches zurück greifen. Letztenendes haben also sowieso alle Leute Zugriff auf die Daten, mein (End-)Programm stellt im Prinzip nur eine Option zur Präsentation der Daten dar.

    Falls ich da nicht eindeutig war: Es geht mir nicht darum, eine feste Datenbank-Struktur zu haben, sondern darum, die Datenbank-Struktur und die beinhalteten Daten im Dateisystem bearbeiten zu können. Ich will im Prinzip die ganzen manuellen "CREATE TABLE"- und "INSERT"-Operationen verallgemeinert automatisieren. Das ganze wird im Prinzip nur ein mal pro Build aufgerufen - die Performance vom Meta-Programm spielt also ansich kaum eine Rolle, während sie im End-Prozess kritisch ist. Wären die ganzen Search&Select-Funktionen von SQL nicht so mächtig, würde ich wohl einfach auf zip oder sogar komplett auf ein Container-Format verzichten.
    Auf der anderen Seite habe ich jetzt wohl schon so viel Zeit in die Lösung dieses Problems gesteckt, dass eine manuelle Lösung letztenendes wohl doch schneller gewesen wäre.
  7. horstexplorer

    horstexplorer hat kostenlosen Webspace.


    Das Problem ergibt sich im wesentlichen bei Punkt 4 - das Parsen der Dateien in Feldname und Datentyp.

    Da gibt es doch eigentlich nur zwei Möglichkeiten dies zu tun, entweder an der Dateierweiterung oder am Inhalt der Datei.
    Mit der Dateierweiterung dürfte die einfachere Methode sein - du müsstest das halt nur irgendwo einmal definieren welche Erweiterung zu welchem Typ gehört (und natürlich eine Regelung falls keine Dateiendung vorhanden ist)

    Owncloud scheint das ganze anhand der Endung nach MIME Typen zu unterteilen und diese Information als Integer in der Datenbank abzulegen. Zwar werden hierbei nicht die Daten in der DB mit abgelegt, es geht ja allerdings eh nur um die Erkennung was es für Daten sind - unabhänig davon wo sie liegen.
    Da gibt es ne schöne Datei welche dafür benutzt wird.
    https://github.com/owncloud/core/tree/master/resources/config

    Daran könnte man zumindest erkennen ob es etwa ein Text, JSON, Binary oder Blob sein könnte (oder halt was du noch definierst)

    Damit der Zugriff möglichst einfach ist könnte man die Spalten genauso benennen wie die Typen - sonst müsste man vermutlich die Information zum eigentlichen Typ noch aus der Info raus ziehen [PRAGMA table_info(table)]

    Also hätte man das irgendwie so
    | UID | path | filename | fileext | mimea | mimeb | stype | text | json | binary | blob | ...
    | 0   | img/  | somefile | jpg     | image | jpeg | blob | null | null | null | ###

    Es ist eigentlich nicht notwendig die MIME Typen noch abzuspeichern da diese ja nur da sind um das Umwandeln der Endung zu unserem Datentypen der Datenbank (stype) etwas zu vereinfachen, allerdings lässt sich so auch besser nach Dateigruppen suchen (Audio, Bilder, etc).

    Einlesen und Exportieren würde damit so funktionieren wie du es bereits beschrieben hast.
    1. Eine Set zum Speichern des Dateipfades (inkl Dateiname etc) erstellen.
    2. Den Ordner im Zielbereich einlesen und den Inhalt der Map hinzufügen.
    3. Erstes Objekt des Sets nehmen und
     - Dateinamen zu Feldname und Datentyp parsen.
       > Pfad
       > Dateiname
       > Dateierweiterung (falls vorhanden)
          > MIME (da man die Dateiendung hat könnte man Eigentlich auf den Teil nach dem / (mimeb) verzichten)
             >sType -> String der Spalte wo die Daten liegen (am besten identisch zum Datentyp)
     - Sollte noch keine Spalte existieren welche nach sType benannt ist muss diese erstellt werden.
     - Daten aus der Datei auslesen (falls vorhanden) und passend speichern.
     - Wenn die Datei ein Ordner ist -Den Ordner im Zielbereich einlesen und den Inhalt dem Set hinzufügen.-
     - Aktuelles Element aus Set entfernen.
    4. 3. So oft wiederholen bis das Set leer ist.




    Beitrag zuletzt geändert: 3.3.2020 15:51:33 von horstexplorer
  8. Autor dieses Themas

    noxious

    Kostenloser Webspace von noxious

    noxious hat kostenlosen Webspace.

    horstexplorer schrieb:
    Da gibt es doch eigentlich nur zwei Möglichkeiten dies zu tun, entweder an der Dateierweiterung oder am Inhalt der Datei.
    Der MIME-Typ ist für sich denke ich vergleichse unbrauchbar, da es ja viele Datentypen gibt, welche am MIME-Typ so gar nicht eindeutig identifiziert werden können. BLOB-Dateien lassen sich damit zwar relativ einfach erkennen, aber Integer und Text-Daten sind vom MIME-Typ her ja im prinzip identisch, ganz zu schweigen von Metainformationen wie PRIMARY KEYS und so weiter.
    Was mir vergleichsweise gut gefällt ist die Lösung mit einer Dateityp-Interpretations-Tabelle. Eigentlich ziemlich naheliegend - es ärgert mich, dass ich zwar darauf gekommen bin, die Tabellenstruktur in einer Datei abzulegen, aber so etwas einfaches übersehen habe. Ich denke, wenn sich nicht noch eine bessere Möglichkeit auftut, werde ich mich auch damit zufrieden geben.(Ich hab auch schon daran gedacht, mir nen Plugin für nen Editor zu schreiben... Aber der Aufwand wäre schon recht unverhältnismäßig.) Anstelle von von JSON werde ich wohl auf eine Art "INI-Format" zurückgreifen, da es vollkommen ausreichend ist, einfacher und potenziell schneller geparsed werden kann - und ich im Prinzip auch schon einen Parser dafür im Projekt habe.

    Vielen Dank für die Idee!
  9. Moin,

    ich habe zwar immer noch nicht verstanden, was das Ziel deiner maßnahme ist, aber wenn es nur darum geht, dateien Durchsuchbar in einer datenbank reinzumüllen, dann wären mein Ansatz:

    -keine sqlite (nicht leistungsfähig genug)
    -ist die struktur von hunderten /tausenden/unbegrenz vielen tabellen erforderlich?

    warum nicht:
    /db_data
    |-t_data_utf8 (id[int], data, [meta])
    |-t_data_ansi (id[int], data, [meta])
    |-[...]
    |-t_data_query (id[int], name[varchar], path[varchar], type[varchar])
    |-t_data_tag(dq_id[int], tag_id[int])
    |-t_tag(id[int], tag[varchar])
    |-v_data_tag_view


    Vorteil: du könntest konvertierungsschwierigkeiten umgehen, ich weiß nicht, ob Binary sauber arbeitet oder trotzdem konvertiert werden muss, ansonsten riecht eine tabelle, metas kannst du dir als einzelne attribs verwursten, wenn du die durchsuchbar machen willst, wie create, modified, ACL, Tags kannst du dir so viele ranhängen wie du lustig bist, vielleicht machst du auch eine tag-Tag zuordentabelle, um gruppierungen vornehmen zu können wie auch immer.

    mongo wäre vermutlich auch nicht schlecht, nur aufgrund schlechter Erfahrungen der letzten Monate, will ich keinen Mongo mehr sehen...

    und für häufiger gebrauchte tags kannst du dir views basteln, um schneller alle Daten zusammen zu haben, wie zum beispiel, wenn du als Tag projektnamen verwendest alle dateien eines projektes...

    Beitrag zuletzt geändert: 4.3.2020 18:00:12 von sebulon
  10. Autor dieses Themas

    noxious

    Kostenloser Webspace von noxious

    noxious hat kostenlosen Webspace.

    sebulon schrieb:
    Moin,

    ich habe zwar immer noch nicht verstanden, was das Ziel deiner maßnahme ist, aber wenn es nur darum geht, dateien Durchsuchbar in einer datenbank reinzumüllen, dann wären mein Ansatz:
    Okay, da ich offenbar nicht ganz deutlich war: Es geht nicht darum, ein beliebiges Dateisystem in eine SQLite-Datenbank umzuwandeln, sondern primär um das Gegenteil: Ich will eine vorhandene SQLite-Datenbank in ein Dateisystem umwandeln, um die Daten einfacher anpassen zu können.

    Nehmen wir folgendes - sehr stark vereinfachtes - Beispiel: Ich habe eine Datenbank, in welcher ich Bilder abspeicher - Sinnhaftigkeit sei erstmal dahin gestellt. Ich habe also beispielsweise die Tabelle "Images", welche einen PRIMARY KEY namens "id" hat, eine TEXT-Feld für eine Beschreibung und ein BLOB-Feld, in welchem die Bilddatei steckt.

    Ich möchte nun das Bild in der Bilddatei bearbeiten - ich muss es also aus der Datenbank ziehen, muss es in einem Bildeditor öffnen, es speichern und dann zurück in die Datenbank schieben. Manuell ein unglaublicher Aufwand - vor allem, wenn man das ganze für hunderte Bilder machen will.
    Das nächste Problem ergibt sich, wenn ich den Funktionsumfang erweitere und beispielsweise ein weiteres Feld mit einem weiteren Bild hinzufügen möchte. Ich müsste nun also die Datenbank-Struktur ändern, die Bilder sortieren und mir ein script schreiben, welches die neuen Bilder in die Datenbank einfügt. Grade im Entwicklungsprozess kommt dies sehr häufig vor was dazu führt, dass ich n% meiner Zeit darauf verwende, Scripte oder Methoden zu schreiben, welche neue Daten in die Datenbank schieben.

    Meine Lösung wäre also: Einfach alle Daten aus der Datenbank ziehen, im Dateisystem unter bestimmten Namenskonventionen ablegen, dort nacheinander editieren, möglicherweise ein paar neue Dateien erstellen und dann alle in einem Schub zurück schieben - defakto also ein mal eine Methode schreibe, welche verallgemeinert mit allen Daten und Datentypen umgeht.

    Das Probelm an der Sache ist, dass das Dateisystem nun mal nicht dafür ausgelegt ist, gewisse Feldinformationen zu speichern - wie speichere ich ob es sich um INT, TEXT oder BLOB handelt, wie behandle ich PRIMARY/FOREIGN KEY, wie definiere ich DEFAULT-Werte, wie sage ich, dass ein Feld UNIQUE ist? Sollte klar sein, worauf ich hinaus will.

    Möglicherweise verwirrt, dass meine Beispiele sich bisher immer nur darauf bezogen, wie man das ganze wieder zurück schiebt - der Grund ist schlicht: Es ist fehleranfälliger und somit ein besserer Test-Kandidat, ob das Parsen eines erstellten Dateisystems auch funktioniert. Wenn ich es schaffe, eine Datenbank aus einem Dateisystem zu erstellen, ist der umgekehrte Weg eher trivial. Diverse Probleme, welche sich beim erstellen der Datenbank ergeben, tauchen beim "herausziehen" der Daten gar nicht auf - zum Beispiel braucht man die ganzen Definitionen der Felder auf dem Dateisystem in die eine Richtung nicht, in die andere aber schon.

    sebulon schrieb:
    -keine sqlite (nicht leistungsfähig genug)
    Ich muss zugeben: Meine Recherchen gehen da noch nicht besonders tief, aber SQLite ist für mich in Sachen Leistungsfähigkeit erstmal gut genug. Andere Formate, welche ich bisher untersucht habe, sind entweder weniger Leistungsfähig oder haben andere Probleme. Die Gründe, weshalb ich mich für SQLite entschieden habe, sind: Es ist schnell (genug), es ist frei und es ist weit verbreitet. Natürlich gibt es schnellere Optionen - ein eigenes, binäres Format wäre vermutlich die schnellste Lösung, aber das würde eine künstliche Barriere für andere Entwickler schaffen, welche möglicherweise einen anderen Präsentationsansatz für die Daten schaffen wollen. Dasselbe gilt für die Lizenz - auch, wenn ich potenziell eher frei, aka "Open Source" arbeite, will ich niemandem Stöcke in die Speichen stecken, welcher was proprietäres daraus machen will. Grade Lösungen wie mongoDB(mit SSPL) sind da ja sehr restriktiv. SQLite ist da eine der wenigen, sehr umgänglichen Lösungen, die mir bisher unter gekommen sind. Dass SQLite sehr weit verbreitet ist, hat zudem den Vorteil, dass die Leute damit vertraut sind und es so erleichtert wird, damit zu arbeiten, ohne sich mehr oder weniger obskure andere Formate aneignen zu müssen. SQLite ist daher für mich von den mir bisher bekannten Varianten der beste Kompromiss zwischen Leistungsfähigkeit und Nutzbarkeit.

    sebulon schrieb:
    -ist die struktur von hunderten /tausenden/unbegrenz vielen tabellen erforderlich?
    Grundsätzlich? Ja. Praktisch werden es wahrscheinlich nicht mehr als Hundert Tabellen, aber wenn der Funktionsumfang erweitert wird, soll Raum nach oben da sein.

    Wie schon weiter oben beschrieben ist meine bisher bevorzugte Lösung jene die von horstexplorer vorgeschlagen/inspiriert wurde, einfach eine ini-Datei im Wurzel-Verzeichnis zu hinterlegen, in welcher dann die jeweiligen Konventionen zu Datentypen und sonstiges als Map hinterlegt sind. Durch diese kann ich dann einfach iterieren, die SQL-Query für die Erstellung der Tabelle erstellen und letztenendes die Daten rein schieben. Das Herausziehen der Daten ist da ziemlich trivial - man iteriert durch die Tabellen, selected * und speichert die jeweiligen Felder unter den angegebenen Namenskonventionen. Eine unkomplizierte Lösung, welche im wesentlichen genau das tut, was ich vorhatte - auch, wenn ich gerne auf eine Struktur-Datei verzichtet hätte. Aber mit der Zeit kommen ja schließlich mmer weniger "neue" Datentypen hinzu.
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!