(BLOCK (PARA (TEXT "A search term allows you to specify one search restriction.") (SOFT) (TEXT "The result ") (LINK-ZETTEL () "00001007700000" (TEXT "search expression")) (TEXT ", which contains more than one search term, will be the applications of all restrictions.")) (PARA (TEXT "A search term can be one of the following (the first three term are collectively called ") (FORMAT-EMPH () (TEXT "search literals")) (TEXT "):")) (UNORDERED (BLOCK (PARA (TEXT "A metadata-based search, by specifying the name of a ") (LINK-ZETTEL () "00001006010000" (TEXT "metadata key")) (TEXT ", followed by a ") (LINK-ZETTEL () "00001007705000" (TEXT "search operator")) (TEXT ", followed by an optional ") (LINK-ZETTEL () "00001007706000" (TEXT "search value")) (TEXT ".")) (PARA (TEXT "All zettel containing the given metadata key with a allowed value (depending on the search operator) are selected.")) (PARA (TEXT "If no search value is given, then all zettel containing the given metadata key are selected (or ignored, for a negated search operator)."))) (BLOCK (PARA (TEXT "An optional ") (LINK-ZETTEL () "00001007705000" (TEXT "search operator")) (TEXT ", followed by a ") (LINK-ZETTEL () "00001007706000" (TEXT "search value")) (TEXT ".")) (PARA (TEXT "This specifies a full-text search for the given search value.")) (PARA (TEXT "However, the operators ") (FORMAT-QUOTE () (TEXT "less")) (TEXT " and ") (FORMAT-QUOTE () (TEXT "greater")) (TEXT " are not supported, they are internally translated into the ") (FORMAT-QUOTE () (TEXT "match")) (TEXT " operators.") (SOFT) (TEXT "Similar, ") (FORMAT-QUOTE () (TEXT "not less")) (TEXT " and ") (FORMAT-QUOTE () (TEXT "not greater")) (TEXT " are translated into ") (FORMAT-QUOTE () (TEXT "not match")) (TEXT ".") (SOFT) (TEXT "It simply does not make sense to search the content of all zettel for words less than a specific word, for example.")) (PARA (FORMAT-STRONG () (TEXT "Note:")) (TEXT " the search value will be normalized according to Unicode NKFD, ignoring everything except letters and numbers.") (SOFT) (TEXT "Therefore, the following search expression are essentially the same: ") (LITERAL-INPUT () "\"search syntax\"") (TEXT " and ") (LITERAL-INPUT () "search syntax") (TEXT ".") (SOFT) (TEXT "The first is a search expression with one search value, which is normalized to two strings to be searched for.") (SOFT) (TEXT "The second is a search expression containing two search values, giving two string to be searched for."))) (BLOCK (PARA (TEXT "A metadata key followed by ") (FORMAT-QUOTE () (LITERAL-INPUT () "?")) (TEXT " or ") (FORMAT-QUOTE () (LITERAL-INPUT () "!?")) (TEXT ".")) (PARA (TEXT "Is true, if zettel metadata contains / does not contain the given key."))) (BLOCK (PARA (TEXT "The string ") (LITERAL-INPUT () "OR") (TEXT " signals that following search literals may occur alternatively in the result.")) (PARA (TEXT "Since search literals may be negated, it is possible to form any boolean search expression.") (SOFT) (TEXT "Any search expression will be in a ") (LINK-EXTERNAL () "https://en.wikipedia.org/wiki/Disjunctive_normal_form" (TEXT "disjunctive normal form")) (TEXT ".")) (PARA (TEXT "It has no effect on the following search terms initiated with a special uppercase word."))) (BLOCK (PARA (TEXT "The string ") (LITERAL-INPUT () "PICK") (TEXT ", followed by a non-empty sequence of spaces and a number greater zero (called ") (FORMAT-QUOTE () (TEXT "N")) (TEXT ").")) (PARA (TEXT "This will pick randomly N elements of the result list, preserving the order of that list.") (SOFT) (TEXT "A zero value of N will produce the same result as if nothing was specified.") (SOFT) (TEXT "If specified multiple times, the lower value takes precedence.")) (PARA (TEXT "Example: ") (LITERAL-INPUT () "PICK 5 PICK 3") (TEXT " will be interpreted as ") (LITERAL-INPUT () "PICK 3") (TEXT "."))) (BLOCK (PARA (TEXT "The string ") (LITERAL-INPUT () "ORDER") (TEXT ", followed by a non-empty sequence of spaces and the name of a metadata key, will specify an ordering of the result list.") (SOFT) (TEXT "If you include the string ") (LITERAL-INPUT () "REVERSE") (TEXT " after ") (LITERAL-INPUT () "ORDER") (TEXT " but before the metadata key, the ordering will be reversed.")) (PARA (TEXT "Example: ") (LITERAL-INPUT () "ORDER published") (TEXT " will order the resulting list based on the publishing data, while ") (LITERAL-INPUT () "ORDER REVERSE published") (TEXT " will return a reversed result order.")) (PARA (TEXT "An explicit order field will take precedence over the random order described below.")) (PARA (TEXT "If no random order is effective, a ") (LITERAL-CODE () "ORDER REVERSE id") (TEXT " will be added.") (SOFT) (TEXT "This makes the sort stable.")) (PARA (TEXT "Example: ") (LITERAL-CODE () "ORDER created") (TEXT " will be interpreted as ") (LITERAL-CODE () "ORDER created ORDER REVERSE id") (TEXT ".")) (PARA (TEXT "Any ordering by zettel identifier will make following order terms to be ignored.")) (PARA (TEXT "Example: ") (LITERAL-CODE () "ORDER id ORDER created") (TEXT " will be interpreted as ") (LITERAL-CODE () "ORDER id") (TEXT "."))) (BLOCK (PARA (TEXT "The string ") (LITERAL-INPUT () "RANDOM") (TEXT " will provide a random order of the resulting list.")) (PARA (TEXT "Currently, only the first term specifying the order of the resulting list will be used.") (SOFT) (TEXT "Other ordering terms will be ignored.")) (PARA (TEXT "A random order specification will be ignored, if there is an explicit ordering given.")) (PARA (TEXT "Example: ") (LITERAL-INPUT () "RANDOM ORDER published") (TEXT " will be interpreted as ") (LITERAL-INPUT () "ORDER published") (TEXT "."))) (BLOCK (PARA (TEXT "The string ") (LITERAL-INPUT () "OFFSET") (TEXT ", followed by a non-empty sequence of spaces and a number greater zero (called ") (FORMAT-QUOTE () (TEXT "N")) (TEXT ").")) (PARA (TEXT "This will ignore the first N elements of the result list, based on the specified sort order.") (SOFT) (TEXT "A zero value of N will produce the same result as if nothing was specified.") (SOFT) (TEXT "If specified multiple times, the higher value takes precedence.")) (PARA (TEXT "Example: ") (LITERAL-INPUT () "OFFSET 4 OFFSET 8") (TEXT " will be interpreted as ") (LITERAL-INPUT () "OFFSET 8") (TEXT "."))) (BLOCK (PARA (TEXT "The string ") (LITERAL-INPUT () "LIMIT") (TEXT ", followed by a non-empty sequence of spaces and a number greater zero (called ") (FORMAT-QUOTE () (TEXT "N")) (TEXT ").")) (PARA (TEXT "This will limit the result list to the first N elements, based on the specified sort order.") (SOFT) (TEXT "A zero value of N will produce the same result as if nothing was specified.") (SOFT) (TEXT "If specified multiple times, the lower value takes precedence.")) (PARA (TEXT "Example: ") (LITERAL-INPUT () "LIMIT 4 LIMIT 8") (TEXT " will be interpreted as ") (LITERAL-INPUT () "LIMIT 4") (TEXT ".")))) (PARA (TEXT "You may have noted that the specifications of first two items overlap somehow.") (SOFT) (TEXT "This is resolved by the following rule:")) (UNORDERED (INLINE (TEXT "A search term containing no ") (LINK-ZETTEL () "00001007705000" (TEXT "search operator character")) (TEXT " is treated as a full-text search.")) (INLINE (TEXT "The first search operator character found in a search term divides the term into two pieces.") (SOFT) (TEXT "If the first piece, from the beginning of the search term to the search operator character, is syntactically a metadata key, the search term is treated as a metadata-based search.")) (INLINE (TEXT "Otherwise, the search term is treated as a full-text search."))) (PARA (TEXT "If a term like ") (LITERAL-INPUT () "PICK") (TEXT ", ") (LITERAL-INPUT () "ORDER") (TEXT ", ") (LITERAL-INPUT () "ORDER REVERSE") (TEXT ", ") (LITERAL-INPUT () "OFFSET") (TEXT ", or ") (LITERAL-INPUT () "LIMIT") (TEXT " is not followed by an appropriate value, it is interpreted as a search value for a full-text search.") (SOFT) (TEXT "For example, ") (LITERAL-INPUT () "ORDER 123") (TEXT " will search for a zettel containing the strings ") (FORMAT-QUOTE () (TEXT "ORDER")) (TEXT " (case-insensitive) and ") (FORMAT-QUOTE () (TEXT "123")) (TEXT ".")))