Ich entwickle eine Anwendung , die speichern müssen inline , intext Metadaten. Damit meine ich Folgendes: Nehmen wir an, wir haben einen langen Text und möchten einige Metadaten speichern, die mit einem bestimmten Wort oder Satz des Textes verbunden sind.
Wie können diese Informationen am besten gespeichert werden?
Mein erster Gedanke war, eine Art Markdown
Syntax in den Text aufzunehmen , die dann beim Abrufen analysiert wird. So etwas sieht aus:
Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
sed diam __nonummy nibh__[@note this sounds really funny latin]
euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
Dies würde zwei Probleme aufwerfen, die mir einfallen:
- Eine relativ kleine ist, dass, wenn die Syntax zufällig auf dem Text ist, es mit dem Parsen verwirren kann.
- Das wichtigste ist , dass dies nicht behauptet diese Metadaten getrennt vom Text selbst.
Ich hätte gerne eine diskrete Datenstruktur, um diese Daten zu speichern, eine andere DB-Tabelle, in der diese Metadaten gespeichert sind, damit ich sie auf diskrete Weise verwenden kann: Abfragen, Statistiken, Sortieren und so weiter.
EDIT: Da der Antwortende seine Antwort gelöscht hat, denke ich, dass es gut sein könnte, seinen Vorschlag hier hinzuzufügen, da es ein praktikabler Vorschlag war, der dieses erste Konzept erweiterte. Das Poster schlug vor, eine ähnliche Syntax zu verwenden, die Metadaten jedoch mit der PRIMARY KEY
der metadata
Datenbanktabelle zu verknüpfen .
Etwas, das so aussehen würde:
Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
sed diam __nonummy nibh__[15432]
euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
Wo 15432
wäre die ID
einer Tabellenzeile, die die notwendigen, abfragbaren Informationen enthält, wie im folgenden Beispiel.
Mein zweiter Gedanke war, Informationen dieser Art in einer DB-Tabelle zu speichern, die so aussieht:
TABLE: metadata
ID TEXT_ID TYPE OFFSET_START OFFSET_END CONTENT
1 lipsum note 68 79 this sounds really funny latin
Auf diese Weise würden die Metadaten eine eindeutige ID, ein text_id
als Fremdschlüssel der Tabelle verbunden , um die Texte zu speichern und es würde die Daten mit dem Text selbst mit einem einfachen Charakter verbindet Offset - Bereich .
Dies würde den Trick tun, die Daten von den Metadaten getrennt zu halten , aber ein Problem, das ich bei diesem Ansatz sofort sehe, ist, dass der Text grundsätzlich nicht editierbar wäre . Oder, wenn ich die Bearbeitung des Texts nach der Zuweisung von Metadaten implementieren wollte, müsste ich grundsätzlich die Hinzufügung oder Entfernung von Zeichen im Vergleich zur vorherigen Version berechnen und prüfen, ob jede dieser Änderungen vor oder nach jeder Änderung Zeichen hinzufügt oder entfernt der zugehörigen Metadaten.
Das klingt für mich nach einer wirklich uneleganten Herangehensweise.
Haben Sie Hinweise oder Vorschläge, wie ich das Problem angehen könnte?
Edit 2: Einige XML-Probleme
Hinzufügen eines weiteren Falls, der eine Trennung von Daten und Metadaten erforderlich machen würde.
- Angenommen, ich möchte es verschiedenen Benutzern ermöglichen, unterschiedliche Metadatensätze desselben Texts zu haben , wobei jeder Benutzer die Metadaten der anderen Benutzer anzeigen kann oder nicht.
Eine Lösung der Art Markdown (oder HTML oder XML) wäre an dieser Stelle schwierig zu implementieren. Die einzige Lösung in diesem Fall, über die ich nachdenken könnte, wäre, eine weitere DB-Tabelle zu haben, die die Einzelbenutzerversion des Originaltexts enthält und über a mit der Originaltexttabelle verbunden wird FOREIGN KEY
.
Ich bin mir nicht sicher, ob das auch sehr elegant ist.
- XML hat ein hierarchisches Datenmodell: jedes Element , das sein geschieht innerhalb der Grenzen eines anderen Elements als sein betrachteten Kind , die am häufigsten ist nicht der Fall in dem Datenmodell ich suche; In XML muss jedes untergeordnete Element geschlossen werden, bevor das übergeordnete Tag geschlossen werden kann, damit sich die Elemente nicht überschneiden.
Beispiel:
<note content="the beginning of the famous placeholder">
Lorem ipsum dolor sit<comment content="I like the sound of amet/elit">
amet</note>
, consectetuer adipiscing elit</comment>
,<note content="adversative?">
sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.<note content="funny latin">
</note>
</note>
Hier haben wir zwei verschiedene Probleme:
Verschiedene Elemente überlappen sich: Der erste Kommentar beginnt innerhalb der ersten Note, endet aber nach dem Ende der ersten Note, dh es ist nicht ihr Kind.
Gleiche Elemente überlappen sich: Die letzte Note und die fettgedruckte Note überlappen sich; Da es sich jedoch um die gleiche Art von Element handelt, würde der Parser das zuletzt geöffnete Element beim ersten Schließen und das erste geöffnete Element beim letzten Schließen schließen, was unter diesen Umständen nicht beabsichtigt ist.
quelle
Antworten:
Ich würde eine Mischung aus Ihren Lösungen wählen, aber stattdessen würde ich einen Standard verwenden: XML. Sie würden eine Syntax wie diese haben
Warum XML?
Wenn Sie darüber nachdenken, ist es genau so, wie das gesamte Web strukturiert ist : Inhalt (tatsächlicher Text), der semantisch ist - das, was Sie Metadaten nennen durch HTML-Tags .
Auf diese Weise haben Sie eine wirklich coole Welt, die sich öffnet:
Lorem <note>ipsum</note>
wenn Sielorem ips*
zum Beispiel suchen .Warum XML über Markdown
Bei einer Website wie stackexchange wird Markdown verwendet, da die Semantik des Inhalts eher grundlegend ist: Hervorhebung, Links / URLs, Bild, Header usw. Die Semantik, die Sie Ihrem Inhalt hinzufügen, scheint zu sein
Aus diesem Grund halte ich Markdown nicht für eine gute Idee. Auch Markdown ist nicht wirklich standardisiert, und Parsing / Dumping könnte ein Nervenkitzel sein, noch mehr eine abwertende Syntax, siehe Jeff Atwoods Post über die WTF, die er beim Parsen von Markdown getroffen hat .
Bei der Trennung zwischen Daten und Metadaten
Eine solche Trennung ist an sich nicht obligatorisch. Ich nehme an, Sie suchen den Vorteil, den es bringt:
All diese Bedenken werden durch die Verwendung von XML ausgeräumt. Aus dem XML-Code können Sie problemlos Inhalte mit entferntem Tag sichern, und Daten / Metadaten werden ebenso wie Attribut- und tatsächlicher Text in XML getrennt.
Ich glaube auch nicht, dass Sie Ihre Metadaten wirklich nicht an Ihre Daten binden können . Nach dem, was Sie beschreiben, sind Ihre Metadaten eine Zusammensetzung Ihrer Daten, dh das Löschen der Daten führt zum Löschen von Metadaten. Hier weichen die Metadaten vom üblichen HTML / CSS ab. CSS verschwindet nicht, wenn ein HTML-Element entfernt wird, da es auf andere Elemente angewendet werden kann. Ich glaube nicht, dass dies in Ihren Metadaten der Fall ist.
Wenn Sie Metadaten in der Nähe der Daten haben, wie z. B. in XML oder Markdown, können Sie die Daten leicht verstehen (und möglicherweise debuggen). Auch das Beispiel, das Sie bei Ihrem zweiten Gedanken anführen, erhöht die Komplexität, da ich für alle Daten, die ich lese, die Metadatentabelle abfragen muss, um diese abzurufen. Wenn die Beziehung zwischen Ihren Daten und Ihren Metadaten 1: 1 oder 1: N ist, dann ist IMO eindeutig nutzlos und bringt nur Komplexität mit sich (ein gutes Beispiel für YAGNI).
quelle
Anwendungsfall der Lösung
Ich bin mit einigen der anderen Antworten nicht einverstanden, weil sie, obwohl sie großartige Lösungen sind, wahrscheinlich nicht Ihre Lösung sind. Ja, XML enthält das Wort Markup im Akronym, aber es ist wahrscheinlich nicht ideal für Ihre Situation. Es ist viel zu komplex und bietet wenig Unterstützung, um die Metadaten vom Originaltext zu trennen. Im Wesentlichen wird alles in eine Form von Metadaten umgewandelt, wodurch ein übergewichteter Datensatz erstellt wird.
Da es wahrscheinlich keine absolut korrekte Lösung oder Vorgehensweise gibt, beantwortet die beste Lösung die Frage:
Wenn Sie sich fragen, wie ein Lösungsdesign den Wert des Systems in der Art und Weise, wie es verwendet wird, von Natur aus steigern kann, sind Sie der Suche nach Ihrer eleganten Antwort näher .
Das Problem verstehen
Okay, genug Kommentar, lasst uns das Problem untersuchen. Dies ist das Problem, wie ich es verstehe (offensichtlich wird es von Vorteil sein, es zu ergänzen):
Aufbau des Lösungsdesigns
Nachdem ich das oben beschriebene Problem verstanden habe, werde ich nun mögliche Lösungen und Ansätze vorschlagen, die darauf abzielen, das oben genannte Problem zu lösen.
Komponenten
Ich würde also sehen, dass es ein benutzerdefiniertes Benutzerzugriffssystem geben muss. Es würde relevante und irrelevante Metadaten aus dem Originaltext herausfiltern. Dies würde das Bearbeiten und Anzeigen von Metadaten im Text erleichtern. Dies würde die Integrität der Beziehung zwischen den Metadaten und dem Originaltext sicherstellen. Es würde die Metadaten strukturieren und eine Datenquelle für ein relationales Datensystem bereitstellen. Es wird höchstwahrscheinlich eine Vielzahl anderer zweckgebundener Funktionen bieten.
Struktur
So , da es wichtig ist , die Metadaten der Integrität auf den ursprünglichen Text zu halten, ist der beste Weg , um dies zu gewährleisten, ist die Metadaten zu halten inline mit dem ursprünglichen Text. Dies bietet den Vorteil, dass die Originaldaten sicher bearbeitet werden können, ohne diese Integrität zu beeinträchtigen.
Die Bedenken bei diesem Ansatz sind die Beschädigung der Metadaten durch die Originaldaten und umgekehrt. Die angemessene Indizierung und Strukturierung der Metadaten und ihrer (Meta-) Metadaten auf eine Weise, die Abfragen und Aktualisierungen sowie einen effizienten Zugriff ermöglicht. Das einfache Filtern von Metadaten aus dem Originaltext.
In diesem Sinne würde ich vorschlagen, dass ein Teil der Lösung auf dem Ansatz basiert, ESCAPE CHARACTERS im Originaltext zu verwenden. Dies ist nicht dasselbe wie das Entwerfen einer eigenen Auszeichnungssprache oder das Verwenden einer vorhandenen Auszeichnungssprache wie XML oder HTML. Es ist einfach, ein ESCAPE-ZEICHEN zu entwerfen , bei dem die Wahrscheinlichkeit, dass es im Originaltext existiert, Null oder nahezu Null beträgt .
Beispieldaten mit Escape-Sequenzen
Dies ist eine Geschichte eines Mannes. >>>> (#) Warum handelt es sich bei dieser Geschichte um einen Mann nicht um eine Frau? (#) ( ) Userid :: 77367 ( ) Kommentar des Managers ( ) DataID :: 234234234 >>>> Ein Mann, der eine Wiese mähen wollte, ging eine Wiese mähen. Der Mann ging mit seinem Hund >>>> (#) Fragen Sie den Kunden, ob die Geschichte mit einer Katze besser wäre (#) >>>>, um die Wiese zu mähen. Das ist also die Geschichte eines Mannes und seines Hundes, die eine Wiese mähen wollten.
Ein Mann und sein Hund gingen, um eine Wiese zu mähen, gingen, um eine Wiese zu mähen, eine Wiese, die über den Berg reichte. >>>> (#) Das klingt viel besser mit einem Wald (**) Hinweis auf Vorschläge (#) >>>>
Der Mann und sein Hund und sein Auftrag, eine Wiese zu mähen, eine Wiese, die über den Berg reicht, wird nur beim Überqueren des Flusses erreicht.
Beispieldaten ohne Escape-Sequenzen
Dies ist eine Geschichte eines Mannes. Ein Mann, der ging, um eine Wiese zu mähen, ging, um eine Wiese zu mähen. Der Mann ging mit seinem Hund, um die Wiese zu mähen. Das ist also die Geschichte eines Mannes und seines Hundes, die eine Wiese mähen wollten.
Ein Mann und sein Hund gingen, um eine Wiese zu mähen, gingen, um eine Wiese zu mähen, eine Wiese, die über den Berg reichte.
Der Mann und sein Hund und sein Auftrag, eine Wiese zu mähen, eine Wiese, die über den Berg reicht, wird nur beim Überqueren des Flusses erreicht.
Offensichtlich ist dies leicht zu analysieren, nicht komplex als gesamte Markup-Sprache und leicht an Ihren Zweck anzupassen.
Schon gelöst? Nun, ich würde nein sagen. Unsere Lösung hat noch einige Lücken. Die Indizierung und der strukturierte Zugriff auf diese Daten sind schlecht. Es ist auch nicht sinnvoll, diese Datei (oder mehrere Dateien) gleichzeitig mit der Bearbeitung abzufragen.
Wie könnten wir dieses Problem lösen?
Ich würde eine DATA ALLOCATION TABLE als Dokumentenkopf vorschlagen . Ich würde auch vorschlagen, eine TRANSACTIONAL TABLE UPDATE QUEUE zu implementieren . Lassen Sie mich erklären. Die Entwickler eines Dateisystems, insbesondere eines Rotationsdatenträger-Dateisystems, standen vor ähnlichen Designherausforderungen wie die oben beschriebenen. Sie mussten Informationen zu den Dateien auf der Festplatte zusammen mit den Daten einbetten. Eine großartige Lösung für die Beziehungsintegrität dieser Daten bestand darin, sie in einer Dateizuordnungstabelle ( File Allocation Table, FAT) zu duplizieren .
Dies bedeutet, dass für jedes einzelne Metadatenelement ein entsprechender Eintrag in der Datenzuordnungstabelle vorhanden ist . So ist es schnell, strukturiert und relational und unabhängig von den Originaldaten. Wenn für die Metadaten Abfragen, Verknüpfungen oder Aktualisierungen erforderlich sind, können Sie auf einfache Weise auf die Datenzuordnungstabelle zugreifen .
Natürlich muss darauf geachtet werden, dass die ursprünglichen Inline-Metadaten die Daten der Datenzuordnungstabelle widerspiegeln . Hier kommt eine Transaktions-Tabellen-Aktualisierungswarteschlange ins Spiel. Jede Änderung, Hinzufügung oder Entfernung von Metadaten wird nicht an den Daten selbst vorgenommen, sondern an der Warteschlange. Die Warteschlange stellt dann sicher, dass entweder alle Änderungen sowohl an den Inline- als auch an den Tabellendaten vorgenommen werden oder dass überhaupt keine Änderungen vorgenommen werden. Außerdem können asynchrone Aktualisierungen durchgeführt werden. Beispielsweise können alle Metadaten eines bestimmten Benutzers durch Ausführen eines Löschbefehls in der Warteschlange gelöscht werden. Wenn die Inline-Metadaten gesperrt waren und verwendet wurden, führte die Warteschlange keine Änderungen durch, bis dies sowohl für die Tabellendaten als auch für die Inline-Daten möglich war.
quelle
>>>>>(#1) Lorem ipsum (#1)>>>>>>
. Es scheint auch so, als ob Ihre Annäherung an Intext-Kommentare sie an eine bestimmte feste Position binden würde. Wie würde das funktionieren, wenn der Versatz verschoben wird?Dies ist eine typische technische Frage, da alle Ihre Optionen unterschiedliche Kompromisse aufweisen und die beste davon abhängt, was für Sie wichtig ist. Leider haben Sie nicht genügend Informationen angegeben, um eine Entscheidung treffen zu können.
Sie scheinen auch kein wichtiges semantisches Problem in Betracht zu ziehen. Nehmen wir an, der Originaltext ist
Jemand fügt einen Kommentar zu "Bob" hinzu
Dann wird der Originaltext bearbeitet
Sie können diesen speziellen Fall mit einem Textabgleichsalgorithmus, wie z. B. dem zur Anzeige einer Diff-Datei, sinnvoll beschreiben. Durch Zeichenversätze werden die Metadaten jedoch an "Jan" in "Jane" angehängt.
Schlimmer ist es, wenn der Text bearbeitet wird
Sie könnten herausfinden, wie Sie die Metadaten an "Steve" anhängen können, aber woher wissen Sie, ob sie zutreffen?
Haben Sie auch entschieden, ob die Metadaten selbst Metadaten enthalten können? Das könnte Ihre Implementierung ändern.
Abgesehen von semantischen Problemen ist nicht klar, was Sie mit den Daten tun. Ich dachte, es wäre vielleicht sehr unpraktisch, den Originaltext mit Markups zu "verschmutzen", aber dann war es in Ordnung, ID-Werte darin zu haben. Was viele nicht sinnvoll , wenn die Metadaten an einen gelten Abschnitt des Textes statt im Text in einen Punkt eingefügt wird.
Ich vermute, dass das Speichern von markiertem Text für die meisten Zwecke einfacher ist. Alternativ können Sie auch alle SQL-Anweisungen ausführen und den Text und das Markup durch eine Knotenhierarchie darstellen lassen - im Grunde genommen ein DOM in Tabellenform. Wenn Ihre Daten hierarchisch sind, ist es möglicherweise einfacher, XML zu verwenden und vorhandene Parser kostenlos zu erhalten, als eigene zu schreiben.
Es ist durchaus möglich, dass es eine ziemlich einfache Lösung gibt, die für Ihre genaue Situation gut genug ist, aber ich kann Ihnen nicht sagen, was das ist, weil es wirklich davon abhängt, was Sie im Detail zu tun versuchen.
Ich würde Ihnen dringend empfehlen, die von Ihnen gewählte Strategie so weit wie möglich zusammenzufassen, obwohl dies ziemlich schwierig ist, wenn ein Großteil Ihrer Implementierung für viele SQL-Abfragen sichtbar sein muss.
Tut mir leid, dass die Antwort so verstreut und voller "es kommt darauf an" ist, aber echte Designfragen sind so.
quelle
Ich denke, der Vorschlag des vorherigen Antworters, den Sie zu Ihrer Frage erwähnt haben, ist sehr gut.
Es würde sich genauso verhalten, wie wir Links auf den StackExchange-Sites veröffentlichen, aber die Info-Daten würden sich in einer anderen Tabelle befinden. Die Vorteile sind, dass Sie die Daten getrennt und daher abfragbar und indexierbar haben. Wenn Sie den Text bearbeiten, können Sie nach gelöschten Metadaten-IDs suchen und die Metadatentabelle bereinigen.
Das einzige kleine Problem, wie Sie sagten, ist das Parsen, aber Sie können es ziemlich leicht bewältigen.
quelle
Sagen wir, ich habe einen Text:
Ich füge die Notiz so hinzu:
[@123,#456,2w]
bedeutet: user_id = 123, note_id = 456, und der durch diese Notiz markierte Text erstreckt sich über die nächsten 2 Wörter (kann aus Zeichen (c
), Sätzen (s
), Paragraphen (p
) oder was auch immer bestehen). Die genaue Syntax kann natürlich abweichen.In Nur-Text-Editoren kann der Text von Notizen einfach am Ende des Dokuments gespeichert werden, genau wie bei Markdown-Fußnoten.
In Rich-Text-Editoren kann diese Art von Notiz als Symbol im Text angezeigt und markierter Text auf irgendeine Weise hervorgehoben werden. Der Benutzer kann solche Notizen dann wie normale Zeichen mit Deloder löschen Backspaceund sie mit einem speziellen Bearbeitungsmodus bearbeiten. Ich stelle mir vor, die Größe notierter Bereiche mit einer Maus zu ändern und den Notizentext mit einem Popup-Fenster zu bearbeiten.
Vorteile:
Nachteile für die Klartextbearbeitung:
Allgemeine Nachteile:
quelle
nonummy
undnibh
einfügen würde, würde das nicht meine Offsets durcheinander bringen?