\pagebreak

## Suchquery

\includegraphics[scale=0.9]{query.png}

Die Anwendung erlaubt das Eingeben von speziell formatierten Suchanfragen. Diese werden in
textueller Form von der Oberfläche aufgenommen, an den Server weitergeleitet, dort ausgewertet und
dann die Ergebnisse zurück übermittelt. Diese textuellen Anfragen werden als Suchqueries oder auch
kurz Query genannt.

Im folgenden Unterkapiteln wird auf dem Aufbau eines solchen Suchqueries genauer eingegangen.

### Sonderzeichen

Sonderzeichen, sofern sie keinen spezielle Syntax bilden werden ignoriert und nicht in die Suche
eingeschlossen.

### Begriffe

\includegraphics[scale=0.9]{begriff.png}

Begriffe werden mit einem Leerzeichen abgetrennt im Query definiert. Begriffe bestehen nur aus
Zeichen der Zeichenklasse `\w`. Bindestriche dürfen zwischendrin vorkommen, aber nicht am Anfang.
Groß- und Kleinschreibung wird ignoriert.

Es muss nur ein Begriff aus der Liste von Begriffen passen. Passen mehrere fällt das Ranking besser
aus.

**Beispiele:**

- `Apfel` sucht nach allem, wo Apfel vorkommt
- `Apfel Banane` sucht nach allem, wo entweder Apfel oder Banane vorkommt. Wenn beides vorkommt, so
    erhält dies eine höhere Priorität

### Explizite Ausdrücke

\includegraphics[scale=1]{expliziter_ausdruck.png}

Explizite Ausdrücke werden von doppelten Anführungsstrichen `"` umschlossen. Alle Zeichen darin
werden direkt gesucht und es wird nichts umformatiert. Anführungsstriche werden mit `\"` escaped.

**Beispiele:**

- `"Apfel, Banane"` sucht nach allem, wo der Substring "Apfel, Banane" in genau dieser Schreibung
    enthalten ist.

### Optionen

\includegraphics[scale=1]{option.png}

Es gibt verschiedene Optionen. Alle Optionen sind mit dem Schlüssel, einen Doppelpunkt und einen
Wert versehen. Wenn Werte Leerzeichen enthalten, müssen diese mit doppelten Anführungsstrichen `"`
umschlossen werden.

\pagebreak

#### Attribute

\mbox{}\newline\newline\includegraphics[scale=0.95]{attribut.png}

Sucht direkt nach einem Attribut und vergleicht diesen.

> Attribute erzwingen den Typ `person`. Somit sind `type:person attr:age` und
> `attr:age` äquivalent.

Als Schlüssel für diese Operation gilt `attr`. Danach folgt der Attributsschlüssel, ein
Vergleichsoperator und ein Wert.

Folgende Vergleichsoperatoren werden unterstützt:

\begin{longtable}{|p{50pt}|p{40pt}|p{300pt}|}
    \hline
    Operator & Wertetyp & Beschreibung \\
    \hline
    \endhead

    \hline
    \texttt{=} & alle & Das ganze Attribut muss den Wert entsprechen \\
    \hline
    \texttt{\textless{}=}, \texttt{\textless{}}, \texttt{\textgreater{}=},
    \texttt{\textgreater{}}
        & \texttt{int}, \texttt{float}
        & Mathematischer Vergleichsoperator \\
    \hline
    \texttt{\textasciitilde{}=} & \texttt{string} & Attribut muss Wert
    enthalten \\
    \hline
    \texttt{\^{}=} & \texttt{string} & Attribut muss mit Wert anfangen \\
    \hline
    \texttt{\$=} & \texttt{string} & Attribut muss mit Wert aufhören \\
    \hline
    \texttt{@=} & \texttt{string} & Attribut muss einen Regulären Ausdruck
    genügen. Wenn dieser Anführungsstriche, Klammern oder Leerzeichen
    enthält, muss alles in Anführungsstriche gesetzt werden. \\
    \hline
\end{longtable}

Es kann auch der Operator und Wert weggelassen werden, dann wird nur die Existenz des Attributs
geprüft.

\pagebreak

**Beispiele:**

- `attr:age>=5` Sucht nach allen Einträgen, dessen Alter gleich oder größer als 5 ist.
- `attr:opinion` Sucht nach allen Einträgen, die einen Wert für `opinion` haben
- `attr:hasConsent=true` Sucht nach allen Einträgen, die einen Consent hinterlegt haben.
- `attr:opinion@="do(es)?n't like m[ae]n"` Sucht nach allen Einträge mit einen Wert für `opinion`
    welcher einen bestimmten Regulären Ausdruck folgt.

Kann der Vergleichsoperator auf den Wert nicht angewandt werden, so schlägt dieser Teil immer fehl
und trifft auf nichts zu. Dasselbe tritt auch ein, wenn der Reguläre Ausdruck fehlerhaft ist.

#### Felder

\mbox{}\newline\newline\includegraphics[scale=0.95]{feld.png}

Sucht direkt nach einem Feld und vergleicht mit diesen.

Felder sind äquivalent so aufgebaut wie Attribute und arbeiten ähnlich, bieten aber die gleichen
Optionen an.

Felder können bei Interview und Person nur ausgewertet werden, wenn die Confidential Database
verfügbar ist. Wenn nicht, schlägt dies immer zwingend fehl. Es können nur bestimmte Felder
abgerufen werden:

- **Interview**: `time`, `location`, `interviewer`
- **Person**: `name`, `contact`
- **File**: `name`, `kind`

\pagebreak

**Beispiele:**

- `field:name~=Ralf` Das Namensfeld enthält "Ralf"

#### Typ

\mbox{}\newline\newline\includegraphics[scale=1]{typ.png}

Sucht nur bestimmte Arten von Datensätzen ab.

Als Schlüssel gilt `type` und als Wert kann eins der folgenden genutzt werden:

\begin{longtable}{|p{50pt}|p{80pt}|p{260pt}|}
    \hline
    Wert & Beispiel & Beschreibung \\
    \hline
    \endhead

    \hline
    \texttt{interview} & \texttt{type:interview} & Sucht nur nach Interviews \\
    \hline
    \texttt{person} & \texttt{type:person} & Sucht nach einer Person \\
    \hline
    \texttt{file} & \texttt{type:file} & Sucht nach einer Datei (hier werden
    nur die Metadaten berücksichtigt) \\
    \hline
\end{longtable}

#### Rolle

\mbox{}\newline\newline\includegraphics[scale=1]{rolle.png}

Sucht nur noch Interviewten, welche eine Rolle innehaben.

Als Schlüssel gilt `role` und als Wert wird der Schlüssel für die Rolle genutzt:

**Beispiel:**

- `role:doctor` Sucht nach allen Doktoren
- `role:family` Sucht nach allen Familienmitgliedern

#### Sortierung

\mbox{}\newline\newline\includegraphics[scale=0.80]{sort.png}

Sortiert die Ergebnisse nach einem bestimmten Feld oder Score:

> Sortierungen dürfen nur in der obersten Ebene definiert werden! Andernfalls werden diese
> ignoriert.

Als Schlüssel gilt hier `sort`. Der Wert ist in mehrere Teile geteilt, welche mit einem Doppelpunkt
`:` abgetrennt sind.

Als erstes kommt hier die Sorte, dann abhängig von der Sorte noch zusätzliche Optionen und zuletzt
die Richtung.


\begin{longtable}{|p{35pt}|p{40pt}|p{30pt}|p{60pt}|p{200pt}|}
    \hline
    Sorte & Extra Feld & Rich\-tung & Beispiel & Beschreibung \\
    \hline
    \endhead

    \hline
    \texttt{score} & \emph{keins} & \texttt{desc} & \texttt{sort"":score"":desc}
        & Sortiert anhand des resultierenden Scores. \\
    \hline
    \texttt{attr} & Schlüssel & \texttt{asc} & \texttt{sort"":attr"":age"":asc} 
        & Sortiert anhand eines Attributes. \\
    \hline
    \texttt{field} & Schlüssel & \texttt{asc} & \texttt{sort"":field"":name"":asc}
        & Sortiert anhand eines Standardfelds. \\
    \hline
    \texttt{none} & \emph{keins} & \emph{egal} & \texttt{sort"":none} 
        & Sortiert das Ergebnis nicht und gibt sofort alles aus. Dies ist relevant, wenn es schnelle
            Ergebnisse geht und keine großen Datenmengen erwartet werden. \\
    \hline
\end{longtable}

Falls eine Richtung nicht angegeben wird, so wird die standardmäßige Sortierung für die Sorte
genommen.

> Hinweis: `field` ist bei Interview und Person sind nur verfügbar, wenn die Confidential
> Database verfügbar ist. Andernfalls wird diese Sortierung immer ignoriert.

### Operatoren

\includegraphics[scale=1]{operation.png}

Listen von Wörtern können mit Operatoren versehen werden, wodurch diese nur unter bestimmten
Bedingungen erfüllt werden.

#### Negation

\mbox{}\newline\newline\includegraphics[scale=1]{negation.png}

Ein Minus `-` direkt vor einen Ausdruck (es dürfen beliebig viele Leerzeichen zwischen Minus und
Ausdruck stehen) negiert diese Behauptung. Nur solange der interne Ausdruck nicht zutrifft, gilt
dies als erfolgreich.

Alternativ zu einen Minus darf auch ein Ausrufezeichen `!` verwendet werden.

Folgenden mehrere Negationszeichen aufeinander werden diese solange aufgelöst, bis nur noch eins
oder keins mehr übrig ist.

**Beispiele:**

- `-Apfel` sucht nach allem, was keinen Apfel enthält
- `Apfel - Banane` sucht nach allem was Apfel, aber keine Banane enthält.
- `-!--!Apfel` entspricht `-Apfel`

#### AND, OR, XOR

\mbox{}\newline\newline\includegraphics[scale=1]{bool_operation.png}

Diese Operatoren erlauben komplexere Ausdrücke:

\begin{longtable}{|p{50pt}|p{350pt}|}
    \hline
    Operator & Beschreibung \\
    \hline
    \endhead

    \hline
    \texttt{\textbar{}\textbar{}} oder \texttt{\textbar{}}
        & Der komplexe Ausdruck trifft nur zu, wenn eine von beiden Seiten zutrifft. \\
    \hline
    \texttt{\&\&} oder \texttt{\&}
        & Der komplexe Ausdruck trifft nur zu, wenn beide Seiten zutreffen. \\
    \hline
    \texttt{\^{}}
        & Der Ausdruck trifft nur zu, wenn entweder die linke Seite oder die rechte Seite zutrifft.
            Aber niemals beide gleichzeitig. \\
    \hline
\end{longtable}

Die Operatoren dürfen gemischt werden, hierbei gilt aber folgende Priorität: Zuerst wird `^`
ausgewertet, danach `&` und zum Schluss `|`. Falls eine andere Reihenfolge gewünscht ist, so sind
Klammern zu verwenden.

Der Unterschied zwischen den einfachen und doppelten Operator ist beim Scoring. Beim doppelten wird
nur der größte Score weitergegeben. Wobei beim einfachen die Summe genommen wird. Hierrüber lässt
sich also die Priorität in den Suchergebnissen festlegen.

**Beispiele:**

- `Apfel && Banane` Sucht nach allem, wo Apfel **und** Banane gleichzeitig vorkommen.
- `role:doctor || Doctor` Sucht nach allen mit der Rolle Doktor oder wo das Wort Doktor irgendwo
    vorkommt.
- `Apfel ^ Banane` Sucht nach allem, wo entweder Apfel oder Banane vorkommt, aber niemals beides
    gleichzeitig.

##### Unterschiede bei der Sortierreihenfolge

Man nehme an, wir haben folgende Texte, welche in der Datenbank existieren:

- `Apfel Kiwi Birne`
- `Apfel Kiwi`
- `Apfel Banane Birne Kirsche`
- `Apfel Kiwi Kirsche`

Diese werden je nach Query in einer unterschiedlichen Reihenfolge ausgegeben:

- `(apfel kiwi) | (birne | banane | kirsche)`:
    - `Apfel Banane Birne Kirsche`, Score: 4
    - `Apfel Kiwi Birne`, Score: 3
    - `Apfel Kiwi Kirsche`, Score: 3
    - `Apfel Kiwi`, Score: 2
- `(apfel kiwi) || (birne || banane || kirsche)`:
    - `Apfel Kiwi Birne`, Score: 2
    - `Apfel Kiwi`, Score: 2
    - `Apfel Kiwi Kirsche`, Score: 2
    - `Apfel Banane Birne Kirsche`, Score: 1

#### Gruppen

\mbox{}\newline\newline\includegraphics[scale=1]{gruppe.png}

Runde Klammern `(` und `)` können Listen Wörtern gruppieren und somit komplexere Ausdrücke
erstellen.

Falls es nicht genügend schließende Klammern gibt, so wird am Ende aufgefüllt. Gibt es zu viele
schließende Klammern, werden diese ignoriert.

**Beispiele:**
- `Apfel && (Banane Kiwi)` Sucht nach allem, wo zwingend ein Apfel vorkommt und mindestens eins von
    Banane oder Kiwi

#### Auflistung

\mbox{}\newline\newline\includegraphics[scale=1]{auflistung.png}

Wenn Ausdrücke nur von Leerzeichen begrenzt sind, so werden diese zu Listen zusammengefasst. Diese
arbeiten nach speziellen Regeln:

1. Solange keine Optionen enthalten sind, so muss nur eins davon vorkommen. Dies entspräche der
    Logik, dass `Apfel Banane` und `Apfel | Banane` gleich arbeiten.
2. Wenn mehrere Ausdrücke in einer Auflistung zutreffen, so erhöht sich ihr Score. Bei einer
    einfachen Kette von `||` bleibt der Score erhalten.
3. Optionen werden in Auflistungen als zwingend angesehen. Die Auflistung kann somit nur noch
    erfolgreich passen, wenn diese Option erfolgreich ist. Die anderen Ausdrücke behalten ihre
    Logik bei.

    Somit entspräche `role:doctor Doctor House` `role:doctor && (Doctor House)`.
4. Bei der Abarbeitung werden die Optionen immer zuerst abgearbeitet. Erst dann werden sich die
    anderen Ausdrücke angeschaut. Hierbei werden auch Gruppen von Klammern beachtet.

    Somit entspräche `Doctor House role:doctor (attr:age)` 
    `role:doctor && (Doctor House (attr:age))`.

**Hinweis: Jeder Query ist in einer Auflistung eingeschlossen und auch ein leerer Query ist eine
Auflistung. Eine leere Auflistung ist immer Erfolgslos.**

> `()` entspricht somit nichts, `-()` entspricht somit alles

### Scoring

Es wird bei der Abarbeitung des Query's ein Score ermittelt. Hierbei gelten je nach Ausdruck
folgende Regeln:

1. **Begriffe:** Wenn passend, dann `1.0` andernfalls `0.0`
2. **Optionen:** Erzwingt das Fehlschlagen oder Erfolgreich sein von Auflistungen.
3. **Operator:**
    1. **Negation:** Wenn interne Ausdruck großer als 0, dann ist das Ergebnis `0.0`, andernfalls 
        `1.0`
    2. **AND, OR, XOR:** 
        - Mit `&`, `|` und `^`: Ergebnis ist Summe von linken und rechten Ausdruck, wenn Ausdruck
            erfolgreich. Andernfalls `0.0`.
        - Mit `&&` und `||`: Ergebnis ist Maximum vom linken und rechten, wenn Ausdruck
            erfolgreich. Andernfalls `0.0`.
    3. **Gruppen:** Der Score ist immer der Score aus der internen Auflistung
    4. **Auflistung:**
        - Wenn einer der Attribute fehlschlägt: `0.0`
        - Wenn leer: `0.0`
        - Ansonsten Summe der enthaltenden Scorings


### Query-Optimierung

Bevor der Query ausgewertet wird, wird dieser von außen nach innen vereinfacht und somit optimiert.
Die Queries werden in folgender Reihenfolge bearbeitet:

1. Wiederholte gleiche Operatoren, werden auf eine Hierarchie gebracht:
    - `apfel && (banane && kiwi)` entspricht `apfel && banane && kiwi`
2. Negation wird aufgelöst:
    - `-!-!-apfel` entspricht `-apfel`
    - `--apfel` entspricht `apfel`
3. Widersprüchliche Attribute werden aufgelöst:
    - `role:doctor role:family apfel` entspricht `()`
    - `type:interview` wird zu `()` wenn die Confidential Database nicht mehr verfügbar ist.
    - `type:interview attr:age` entspricht `()`
    - `type:person attr:age` entspricht `attr:age`
4. Verundete Gruppen nur aus Attributen werden zusammengefasst:
    - `(role:doctor) && (attr:age=5)` entspricht `(role:doctor attr:age=5)`
5. Wenn eine Auflistung nur eine Gruppe enthält, so wird der Inhalt der Gruppe in die Auflistung
    gezogen:
    - `(((apfel banane)))` entspricht `apfel banane`
    - `(((role:doctor)))` entspricht `role:doctor`
    - `role:doctor ((attr:age))` entspricht `role:doctor (attr:age)`
6. Vorauswertung von booleschen Ausdrücken:
    - `apfel && ()` entspricht `()`
    - `apfel && -()` entspricht `apfel`
    - `apfel || ()` entspricht `apfel`

    Oder hier nocheinmal als übersichtliche Tabelle. `op` steht hierfür für den Operator.


\begin{longtable}{|l|l|l|}
    \hline
    Operator & \texttt{apfel op ()} & \texttt{apfel op -()} \\
    \hline
    \endhead
    \hline
    \texttt{\&} & \texttt{()} & \texttt{apfel \& -()} \\
    \hline
    \texttt{\&\&} & \texttt{()} & \texttt{apfel} \\
    \hline
    \texttt{\textbar{}} & \texttt{apfel} & \texttt{apfel \textbar{} -()} \\
    \hline
    \texttt{\textbar{}\textbar{}} & \texttt{apfel} & \texttt{apfel} \\
    \hline
    \texttt{\^{}} & \texttt{apfel} & \texttt{-apfel} \\
    \hline
\end{longtable}

Der Query wird auf unterschiedliche Tabellen ausgeführt, also wird der Query je nach Tabelle noch
einmal extra umgebaut:

1. Wenn Confidential Database nicht verfügbar ist, wird folgendes optimiert:
    - `type:interview` zu `()` (immer)
    - `field:name` zu `()` (bei Person Tabelle)
2. Einschränkungen des Typs werden konkretisiert:
    - `type:interview` wird zu `()` bei einer Person Tabelle und zu `-()` bei einer Interview
        Tabelle
    - `attr:age` wird zu `()` bei einer Interview oder File Tabelle
    - `role:doctor` wird zu `()` bei einer Interview oder File Tabelle
3. Alle oben genannten Optimierungen werden noch einmal geprüft
4. Sortieralternativen werden ausgewertet:
    - `(sort:field:name a | sort:attr:age b)` zu `sort:field:name (a | b)`
    - `(sort:field:name a || sort:attr:age b)` zu `sort:field:name (a || b)`
    - `(sort:field:name a & sort:attr:age b)` zu `sort:field:name sort:attr:age (a & b)`
    - `(sort:field:name a && sort:attr:age b)` zu `sort:field:name sort:attr:age (a && b)`
    - `(sort:field:name a ^ sort:attr:age b)` zu `a ^ b`
5. Unmögliche Sortierungen oder doppelte Sortierungen entfernt:
    - `sort:field:name:asc sort:field:name:desc a` zu `a`
    - `sort:field:name:asc sort:field:name:asc a` zu `sort:field:name:asc a`

Als nächstes werden sich die Optionen auf der obersten Ebene angeschaut. Diese können die Auswahl
der Tabellen deutlich einschränken. Außerdem sind diese so strukturiert, dass sich diese ohne
weiteres problemlos auf der Datenbank ausführen lassen.

Danach werden sich die anderen Ausdrücke angeschaut. Für jeden wird separat nach folgenden Regeln
entschieden, ob sich dieser auf der Datenbank ausführen lässt:

- Enthält in irgendeiner Tiefe eine Option: Nein
- Enthält in irgendeiner Tiefe eine Auflistung mit mehr als einen Ausdruck: Nein
    > Hier könnte es Probleme mit dem Scoring geben.
- Enthält in irgendeiner Tiefe den Operator `&` oder `|`: Nein
    > Auch hier gibt es ein Scoringproblem.

Alles was sich auf der Datenbank ausführen lässt, wird auch auf dieser ausgeführt. Danach geht der
Server die restlichen Ausdrücke durch, überprüft diese und berechnet einen Score.

Zum Schluss wird nach den Sortierregeln sortiert. Diese werden nur aus der obersten Ebene
genommen und auch in der Reihenfolge abgehandelt. Falls keine Sortierung angegeben ist, so wird
nach dem Score absteigend sortiert.

### Beispiele:

Eine Sammlung von komplexen Beispielen:

- \texttt{attr:age\textgreater{}=30 attr:age\textless{}=50 (field:name sort:field:name\ \textbar{}\textbar{} \newline{}sort:field:age:desc)}

    Sucht sich alle Person zwischen 30 und 50 heraus. Solange die Confidential Datenbank noch
    verfügbar ist, wird nach Namen sortiert, andernfalls nach dem Alter absteigend.
- `(type:interview field:location~=London && field:interviewer~=Bob) || attr:location~=Londyn`

    Sucht nach allen Interviews, welche von Bob in London geführt wurden, oder allen Personen,
    dessen `location` Attribut fälschlicherweise `Londyn` enthält.
- `sort:none We need a pretty long example with many words in it`

    Sucht nach allen Datensätzen, welches eins der angegebenen Wörter enthält. Die Sortierung `none`
    sorgt dafür, dass einfach sofort ausgegeben und nicht gewartet werden soll.
- \texttt{\dq{}mail@example.com\dq{} \dq{}http://localhost.de\dq{}}

    Sucht nach Feldern, wo eine spezifische E-Mail-Adresse oder Link vorkommt. Da diese Sonderzeichen
    enthalten, müssen diese in doppelten Anführungsstrichen `"` gesetzt werden.
