UNIXwork

Fulltext Search Engines Teil 1: Lucene, Solr und Elasticsearch

21. December 2019

Lucene

Apache Lucene ist ein Fulltext Search Engine, die als Java-Bibliothek in eigene Programme eingebunden werden kann.

Lucene arbeitet mit Dokumenten, die verschiedene Felder besitzen können. Felder haben einen Namen und einen Wert. Diese Dokumente können dann zu einem Index hinzugefügt werden. Die Suche nach Dokumenten kann sich dabei auf mehrere Felder beziehen.

Lucene bietet dabei sehr umfangreiche Suchmöglichkeiten. Unterstützt wird außerdem auch ein Ranking der Suchergebnisse.

Im Prinzip lässt sich sagen, dass Apache Lucene die Feature-Messlatte für Open-Source-Volltextsuchen angibt.

Apache Solr

Apache Solr ist ein sehr verbreiteter Suchserver, der auf Apache Lucene aufbaut und den Funktionsumfang davon weitgehend über eine REST-Schnittstelle zur Verfügung stellt. Apache Solr kann man auch als Cluster betreiben und erhält damit ein skalierbares und hochverfügbares System.

Während Lucene nur einfachen Text indizieren kann, ist es mit Apache Solr möglich, verschiedene Dokumententypen zu verarbeiten. Hierfür gibt es verschiedene Content Handler, die Text aus unterschiedlichen Dateitypen extrahieren können.

Der Zugriff auf die REST-Schnittstelle kann man mit Tools wie curl oder anderen HTTP-Clients erfolgen. Es gibt allerdings auch diverse Client-Libs für alle möglichen Programmiersprachen.

Elasticsearch

Genau wie Apache Solr ist Elasticsearch ein Suchserver auf Lucene-Basis. Allerdings handelt es sich um eine kommerzielle Software, wobei ein Teil auch unter einer Open Source Lizenz steht.

Elasticsearch kann ebenfalls als verteilte Searchengine betrieben werden. Zusätzlich bietet es auch diverse Analysewerkzeuge.

Fazit

Mit Apache Lucene steht einem eine sehr mächtige Volltextsuche zur Verfügung, die sich auch recht leicht verwenden lässt (dazu mehr in einem weiteren Artikel). Die selbe Funktionalität steht einem dann auch in größerer Dimension mit Apache Solr und Elasticsearch zur Verfügung.

Autor: Olaf | 0 Kommentare | Tags: apache, lucene, solr, java, db

dav-sync: Symlinks synchronisieren

20. December 2019

Mit dav-sync ist es nun möglich, Symlinks zu synchronisieren. Eine Besonderheit dabei ist, dass unter Windows Verknüpfungen von dav-sync als Symlink interpretiert werden. Windows hat zwar auch richtige Symlinks, die sind aber Mist, da normale Benutzer beispielsweise keine anlegen dürfen.

Beim Synchronisieren wird dann für die Verknüpfung oder Symlink eine leere Resource angelegt und die relative Adresse des Targets in einer WebDAV-Property gespeichert. Damit hat man ein automatisches Mapping zwischen Symlinks und Windows-Verknüpfungen. Wer also gerne über Links seine Dateien organisiert, kann dies nun auch plattformübergreifend synchronisieren. Das gibt es sonst nirgends.

Konfigurieren muss man dafür nicht viel. In die sync.xml muss innerhalb des <directory>-Elements nur folgendes eingefügt werden:

<directory>

    ...

    <symlink-intern>sync</symlink-intern>

</directory>

Synchronisiert werden können dabei nur Links, die ein Target innerhalb des Sync-Directory haben. Links mit externen Targets können aus Sicherheitsgründen nicht synchronisiert werden.

Neben sync gibt es für das <symlink-intern>-Element noch zwei Werte, die angegeben werden können. Zum einen follow, womit angegeben wird, dass Symlinks gefolgt werden soll. Das Ziel wird als normale Datei hochgeladen. Dies ist auch der Default. Die andere Möglichkeit ist ignore, womit dav-sync dann Symlinks nicht mehr folgt, sondern ignoriert.

Es gibt auch noch das Element <symlink-extern> für Links mit einem externen Target. Hier sind die Werte follow und ignore möglich. Wie erwähnt ist sync, also das Synchronisieren von externen Links, nicht möglich.

Autor: Olaf | 0 Kommentare | Tags: dav, sync

dav-sync Datei-Splitting

19. December 2019

Seit dav-sync 1.3 gibt es das Feature, dass Dateien nicht nur als Ganzes synchronisiert werden können, sondern auch nur Teile einer Datei. Hierfür wird für die Datei eine feste Block-Größe definiert und die Datei wird dann in mehrere Blöcke mit dieser Größe eingeteilt. Lokal wird dann pro Block ein Hash gespeichert, so dass erkannt werden kann, welcher Block geändert wurde und synchronisiert werden muss. Auf dem Server wird statt der Datei eine Collection angelegt, in der die einzelnen Blöcke abgelegt werden.

Das Ganze funktioniert natürlich auch Problemlos mit Verschlüsselung. Jeder Block wird als eigenständige Datei hochgeladen und dabei wie sonst auch mit AES im CBC-Mode verschlüsselt.

Natürlich muss man, um das Feature zu nutzen, mal wieder etwas konfigurieren. Zunächst sollte man sich überlegen, welche Dateien überhaupt zerlegt werden sollen. Mögliche Konfigurationsmöglichkeiten sind zum einen, Dateien mit bestimmten Namen oder Pfaden auszuwählen, zum anderen kann auch eine Mindestdateigröße angegeben werden, ab der Dateien aufgeteilt werden sollen.

Die andere Sache, die man sich überlegen muss, ist, welche Größe die einzelnen Blöcke haben sollen. Diese sollte nicht zu klein sein, da sonst viele tausende kleine Dateien auf dem Server abgelegt werden könnten.

Die Konfiguration erfolgt dann in der Datei sync.xml. Hier muss innerhalb des Sync-Directory folgendes eingefügt werden:

<directory>
    ...

    <splitconfig>
    <!-- split all files with .vmdk file extension that are bigger than 100mb -->
        <split>
            <blocksize>10m</blocksize>
            <filter>
                <include>\.vmdk$</include>
            </filter>
            <minsize>100m</minsize>
        </split>
    </splitconfig>
</directory>

Pflichtangabe ist das Element <blocksize>. Damit wird die Blockgröße in Bytes, alternativ auch mit einem Suffix wie k, m oder g, angegeben. Dazu muss entweder <minsize> oder ein <filter> definiert sein. Beides zusammen geht natürlich auch.

Mit <filter> können Regex-Filter, die auf den Dateipfad angewendet werden, konfiguriert werden. Möglich sind zum einen <include>-Filter, die zunächst definieren, welche Dateien ausgewählt werden sollen. Dies kann dann noch mit <exclude> eingeschränkt werden. Die Doku enthält dazu mehr Details.

Mit <minsize> gibt man die Größe an, die eine Datei mindestens haben muss, damit sie aufgeteilt wird. Gibt man nur dieses Element an, ohne <filter>, kann man also pauschal alle Dateien ab einer bestimmten Größe splitten.

Es können auch mehrere split-Regeln definiert werden. Dazu muss nur innerhalb des Elements <splitconfig> ein weiteres <split>-Element eingefügt werden.

Mehr als die Konfiguration muss man dann auch nicht tun. An der Benutzung von dav-sync ändert sich nichts. Wenn alles korrekt konfiguriert ist, werden dann die entsprechenden Dateien aufgeteilt und nur geänderte Blöcke der Datei werden übertragen. Der Benutzer kriegt davon erstmal nichts mit, außer dass es vielleicht schneller geht.

Eine Einschränkung gibt es allerdings. Datei-Versionierung funktioniert nicht mit gesplitteten Dateien. Genauso funktioniert es nicht, wenn <backup-on-pull>true</backup-on-pull> für das Sync-Directory konfiguriert ist, dass bei jeder Dateiänderung ein Backup der Datei in das Trash-Verzeichnis verschoben wird. Der Grund ist, dass nicht mehr kostengünstig über ein move die Datei gesichert werden kann, weil keine komplette Datei übertragen wird.

Erwähnenswert wäre auch noch, dass Datei-Splitting ohne Konfiguration der sync.xml möglich wäre, denn es kann im Prinzip pro Datei einzelnd festgelegt werden, ob diese gesplittet werden soll. Einfache dav-sync-Befehle, um das festzulegen, haben es jedoch nicht in das Release geschafft und ohne Befehle wäre das zu Hacky für diesen Artikel.

Autor: Olaf | 0 Kommentare | Tags: dav, sync

Datenanalyse in der Shell Teil 4: join

18. December 2019

Mit dem Programm join können Daten aus zwei Dateien verknüpft werden. Dabei werden Zeilen mit gleichen Daten in einem bestimmten Feld zusammengefügt. Das Ganze funktioniert also ähnlich wie ein SQL-JOIN.

Ähnlich wie bei anderen Tools müssen die Daten bereits sortiert sein. Hierbei hilft wie immer sort. Außerdem arbeitet join auch mit Feldern, die durch ein Trennzeichen getrennt sind.

Ein kurzes Beispiel mit einfachen Testdaten. Datei1:

1 jan
2 feb
3 mar
5 may

Datei2:

1 31
2 28
3 31
4 30

Ein Join aus beiden Dateien:

$ join Datei1 Datei2
1 jan 31
2 feb 28
3 mar 31

Standardmäßig wird das Feld 1 aus beiden Dateien verglichen. Möglich ist auch, unterschiedliche Felder zu nehmen. Dafür gibt die es Optionen -1 <feldnummer>, um die Feldnummer für die erste Datei anzugeben. Für die zweite Datei gibt es die Option -2 <feldnummer>. Ebenso ist es möglich, statt Space ein anderes Trennzeichen mit der Option -t <char> anzugeben.

In der Ausgabe dürfte einem auffallen, dass Zeilen, die nicht verbunden werden können, nicht ausgegeben werden (INNER JOIN). Dies lässt sich mit den Optionen -a1 und -a2 ändern. Wenn -a1 angegeben ist, werden von der ersten Datei alle Zeilen ausgegeben, bei -a2 das gleiche für die zweite Datei. Es können auch beide Optionen benutzt werden.

Das war jetzt nur eine einfache 1:1-Beziehung. Mit join funktionieren aber auch 1:n-Beziehungen. Nehmen wir dafür ein paar neue Beispieldaten:

Datei1:

admin 1000 System Administrator
max 1001 Max Mustermann
john 1002 John Doe

Datei2:

max user     20 11. Dez 18:01 report.pdf
max user     12 11. Dez 17:56 calc.txt
admin admin  78  8. Dez 10:52 list.txt
john user    24 18. Dez 17:22 stuff1
john user    20 18. Dez 17:22 stuff2
max user     12 11. Dez 18:09 newfile1.txt
max user     10 11. Dez 18:09 todo.txt
admin admin 109  8. Dez 11:28 machines.txt
john user    58 25. Nov 07:26 names.txt
john user    42 25. Nov 07:27 states.txt
admin admin 152  7. Dez 17:42 table1
max user     25  8. Dez 10:12 testdata
max user     12 11. Dez 18:08 test.txt

Join:

$ join <(sort Datei1) <(sort Datei2)
admin 1000 System Administrator admin 109 8. Dez 11:28 machines.txt
admin 1000 System Administrator admin 152 7. Dez 17:42 table1
admin 1000 System Administrator admin 78 8. Dez 10:52 list.txt
john 1002 John Doe user 20 18. Dez 17:22 stuff2
john 1002 John Doe user 24 18. Dez 17:22 stuff1
john 1002 John Doe user 42 25. Nov 07:27 states.txt
john 1002 John Doe user 58 25. Nov 07:26 names.txt
max 1001 Max Mustermann user 10 11. Dez 18:09 todo.txt
max 1001 Max Mustermann user 12 11. Dez 17:56 calc.txt
max 1001 Max Mustermann user 12 11. Dez 18:08 test.txt
max 1001 Max Mustermann user 12 11. Dez 18:09 newfile1.txt
max 1001 Max Mustermann user 20 11. Dez 18:01 report.pdf
max 1001 Max Mustermann user 25 8. Dez 10:12 testdata

Funktioniert also auch hier wie in SQL. Da wir pro Zeile in Datei1 mehrere Zeilen in Datei2 haben, werden die Zeilen in Datei1 dupliziert.

Autor: Olaf | 0 Kommentare | Tags: shell, analytics, unix

dav-sync Versioning

17. December 2019

Ich habe in dav-sync von Anfang an die Datensicherheit an erste Stelle gestellt. Geprägt von Horrorgeschichten über Synchronisations-Programme, die massenweise Daten niedergemetzelt haben, wollte ich mir und allen dav-sync Usern dies ersparen. Daher gab es schon von Anfang an als zusätzliche Sicherung das Trash-Verzeichnis, in das Dateien verschoben wurden, statt sie zu löschen.

Neu ist jetzt das Versioning-Feature, womit auf dem Server mehrere Versionen von Dateien gespeichert werden können. Dies ist in zwei Varianten implementiert. Einmal über einfache Kopien von den Dateien, die in einer versteckten Collection abgelegt werden. Die andere Variante nutzt die WebDAV-Erweiterung DeltaV, wofür es jedoch praktisch keine Server-Implementierungen gibt. Noch nicht ;-)

Im Folgenden möchte ich die Konfiguration und die Benutzung der dav-sync Versionierung erläutern.

Zunächst benötigt man natürlich erst einmal eine Konfiguration für ein Verzeichnis, welches synchronisiert werden soll. In diesem Artikel habe ich die Einrichtung und grundlengende Benutzung von dav-sync erklärt. Für die Versionierung muss nur noch die Konfiguration (sync.xml) etwas angepasst werden. Hierfür muss nur innerhalb des <directory>-Elements folgendes ergänzt werden:

<versioning type="simple" always="true" />

Das type="simple" steht für die Versionierung über einfache Kopien der Dateien. Alternativ könnte hier statt simple auch deltav stehen. Hierfür benötigt man natürlich einen DeltaV-kompatiblen Server. Apache, Nextcloud oder praktisch alle anderen WebDAV-Server unterstützten dies jedoch nicht.

Das Attribut always="true" gibt an, dass bei jedem Hochladen einer Datei eine neue Version angelegt werden soll. Hier könnte natürlich auch false angegeben werden, dann wird nur eine neue Version gespeichert, wenn dies manuell angefordert wird. Hierfür gibt es für die dav-sync Kommandos push und archive die Option -S. Wird diese angegeben, wird für jede hochgeladene Datei die vorherige Version gespeichert.

Damit ist die Konfiguration auch schon abgeschlossen. Alte Versionen von Dateien werden standardmäßig in der Collection .dav-version-history (unterhalb des Sync-Directory) abgelegt. Wer will könnte noch den Speicherort der Versions-History mit dem <history>-Element anpassen.

<versioning type="simple" always="true">
    <history>/.backup/</history>
</versioning>

Jetzt werden immer alte Versionen von Dateien gespeichert. Wer hingegen always="false" benutzt, kann beim Uploaden von Dateien folgendermaßen die Version speichern:

$ dav push -S mydir

Um jetzt alte Versionen von Dateien wiederherzustellen, benötigt man zwei dav-sync Befehle: list-versions und restore. Beide Befehle arbeiten mit lokalen Dateipfaden, man kann daher einen absoluten oder relativen Pfad zu der Datei angeben und dav-sync bestimmt dann automatisch das passende Sync-Directory dazu (wenn es eindeutig ist, ansonsten muss man es mit der Option -s angeben). Als Beispiel gehen wir davon aus, dass wir uns in der Shell im Verzeichnis befinden, in dem die Datei liegt.

$ dav-sync list-versions test.txt
name: 1576420562-69ba29c77659c2db
lastmodified: Sun, 15 Dec 2019 10:39:30 GMT
url: https://example.com/webdav/.history/157/1576420562-69ba29c77659c2db

name: 1576420572-b6a1862b0b1c04e6
lastmodified: Sun, 15 Dec 2019 11:12:28 GMT
url: https://example.com/webdav/.history/157/1576420572-b6a1862b0b1c04e6

name: 1576420613-8b1260a7a6943580
lastmodified: Sun, 15 Dec 2019 15:33:06 GMT
url: https://example.com/webdav/.history/157/1576420613-8b1260a7a6943580

list-versions zeigt alle verfügbaren vorherigen Versionen einer Datei an. Was wir aus der Ausgabe benötigen ist das Feld name. Den Namen können wir bei dem Befehl restore benutzen, um diese Version wiederherzustellen.

$ dav-sync restore -V 576420572-b6a1862b0b1c04e6 test.txt
get: /test.txt
Result: 1 file pulled, 0 errors

Dies downloaded die angegebene Version und ersetzt damit die lokale Datei.

Eine Einschränkung ist noch, dass es keine einfache Möglichkeit gibt, gelöschte Dateien wiederherzustellen. Wenn man versehentlich eine Datei löscht, kann man unmittelbar danach zwar mit dav-sync restore -s <syncdir> alle gelöschten Dateien wiederherstellen. Dies funktioniert jedoch nicht mehr, sobald man nach dem Löschen den Befehl push ausführt und somit auf dem Server die Datei gelöscht wird. Dann ist die Datei zwar noch in der History vorhanden, es gibt jedoch keinen Befehl, der die Datei wiederherstellen kann. Da bleibt einem nur übrig, die gesamte History zu durchsuchen.

Autor: Olaf | 0 Kommentare | Tags: dav, sync
Zurück Weiter