<?xml version="1.0" encoding="utf-8"?>
<!--
Application name: sm-searcher
Build time: 2024-10-12T20:40:37.768
Build number: 93
Version: 1.2
Конфигурационные параметры сервера полнотекстового поиска.
Часть параметров из этого конфига можно переопределить через аргументы командной строки.
-->
<config>

    <!--
    Дислокация данных, это то, как искать и где хранятся данные.
    -->
    <location>

        <!--
        Список корневых путей по умолчанию, используются только в том случае, если не заданы корневые
        папки в аргументах командной строки. Это то, где централизовано хранятся данные по всем базам.

        Если здесь задан относительный путь, то он рассчитывается всегда относительно
        параметра "user.dir", который можно явно передать через аргументы командной строки.
        В параметре "user.dir" всегда должен быть полный канонизированный путь.
        -->
        <roots>
            <root>sm-searcher-data</root>
        </roots>

        <!--
        Общий шаблон, по которому формируется путь до папки с индексной базой (бд).
        Путь всегда строится относительно корня, описанного выше в теге "roots/root".
        В рамках сервера, все пути до всех баз отличаются друг от друга только названием базы.
        Поэтому, в шаблоне пути, только папка с названием базы является шаблонизированной
        и описывается атрибутом "dbName". Названия остальных папок задаются атрибутом "name".
        Самый нижний тег "folder" указывает на папку базы, которая может быть папкой с именем бд.
        -->
        <dbPathPattern>
            <folder dbName="????????-????-????-????-????????????"/>
            <folder name="1Cv8FTxt2"/>
            <folder name="db"/>
        </dbPathPattern>

    </location>



    <!--
    Параметры сервера
        app - корневой путь (первый элемент пути - имя приложения).
        port - номер порта по умолчанию.
        host - адрес этого сервера.
        maxSize - максимальный размер пула потоков;
    -->
    <server port="1978" host="0.0.0.0" app="sm-searcher">
        <threadPool maxSize="300">
        </threadPool>
    </server>


    <!--
    Настройки логирования
    -->
    <logging>

        <!--
        Настройки хранения логов в файлах.
        -->
        <logsInFiles enable="false"/>

        <!--
        Настройки общего лога. В общий лог попадают сообщения о жизнедеятельности сервера в целом.
        А сообщения, которые происходят в контексте конкретной БД, логируются папку конкретной БД.
        -->
        <commonLog>

            <!--
            Относительный путь к папке, куда сохраняются логи. Путь всегда задаётся относительно
            первой корневой папки, смотрите "location/roots/root".
            -->
            <folder relativePath="1Cv8FTxt2/logs"/>

        </commonLog>

        <!--
        Детализация логирования для всех логов.
        -->
        <level>INFO</level>

        <!--
        Логировать запросы.
        -->
        <request which="all"/>

        <!--
        Дублирование логов в консоль.
        mode = "all"    - логи выводятся в файлы и в консоль;
        mode = "none"   - логи выводятся только в файлы;
        mode = "off"    - логи выводятся только в файлы;
        mode = "start"  - в консоль выводится только строчка о старте сервера;
        mode = "stop"   - в консоль выводится только строчка об остановке или падении сервера;
        -->
        <console mode="start|stop"/>

    </logging>


    <!--
    Некоторые общие показатели мониторинга, которые мы периодически выводим в лог
    -->
    <monitoring enable="true">
        <!-- Сколько приложение потребляет памяти -->
        <usedMemory enable="true"/>
    </monitoring>


    <!--
    Некоторые параметры могут быть помечены атрибутом onlyFromConfig.
    Это означает, что параметр будет браться только из конфигурации.
    -->

    <!--
    Настройки индексирования
    -->
    <indexing>

        <!--
        Максимальное количество документов на один commit (транзакцию).
        Если умозрительно допустить, что все документы имеют размер solidDocMaxSize, тогда
        возможна ситуация, когда индексация на один индекс может занять в памяти около 600Мб.
        -->
        <maxCommitSize>150</maxCommitSize>

        <!--
        Максимальный размер документа (в символах), который индексируется целиком.
        Если размер документа больше этого значения, он разделяется на отдельные индексируемые части.
        -->
        <solidDocMaxSize>2000001</solidDocMaxSize>

        <!--
        Истина, если нужно при индексации копировать заголовок в поле content.
        Такое бывает необходимо, если стоит режим поиска только по полю content
        (для скорости), но требуется находить текст из заголовков тоже.
        -->
        <copyTitleToContent enable="true"/>

        <!--
        Язык, используемый при индексации. Если пустая строка, значит используется нейтральный к языку анализатор
        текста, который ориентирован на индексацию текста как есть (без применения морфологии).
        Поддерживаемые языки: "ru", "en", "fr", "de", "es", ...
        -->
        <language default="" onlyFromConfig="false"/>


        <!--
        Разрешение на переключение в режим "только для чтения". Такой режим может
        ускорить поиск, если индекс меняется достаточно редко. Переключение в режим чтения
        делается после первичной индексации или если индекс долго стоит без изменений.
        -->
        <readMode allow="false"/>

    </indexing>

    <!--
    Общие настройки слияния сегментов индекса
    -->
    <merge>

        <!--
        Общие настройки запуска форсированного слияния.
        -->
        <forceMerge>

            <!--
            Диапазон в часах, когда предпочтительно запускать слияние.
            count - общее количество часов в диапазоне [0..24];
                    если 0, значит диапазон пустой и слияния не будет;
                    если 24, значит диапазон полностью заполнен и слияние может запуститься когда угодно;
                    если 1, значит диапазон равен одному часу start.
            start - час, с которого начинается диапазон и который входит в диапазон;
            -->
            <preferredHours start="23" count="4"/>


            <!--
            Минимальный период простоя между завершением предыдущего слияния и запуском следующего.
            Рекомендуемое значение равно (24 - mergeHours), где mergeHours - среднее время слияния в часах,
            полученное опытным путём.
            -->
            <idleTime unit="hours" value="18"/>

        </forceMerge>

    </merge>


    <!--
    Настройки прогрева индексов для устранения лагов при поиске.
    -->
    <warmUp>

        <!--
        Сколько процентов данных нужно прогревать в каждом индексе за одну операцию
        -->
        <percent>10</percent>

        <!--
        Запуск операции прогрева целесообразно начинать, если поиск и индексация по
        конкретному индексу базы простаивает больше какого-то времени.
        -->
        <idleTime unit="min" value="5"/>

    </warmUp>


    <!--
    Настройки для всех БД.
    -->
    <database>

        <!--
        preloadIndices означает предварительную загрузку всех индексов при старте сервера для всех БД.
        -->
        <preloadIndices enable="false"/>

    </database>



    <!--
    Настройки поиска
    -->
    <search>

        <!--Ограничения при поиске-->
        <limits>

            <!--Максимальное время поиска в миллисекундах.-->
            <searchTimeout unit="sec" value="120"/>

            <!--
            Ограничения по оператору NEAR для которого операнды содержат шаблоны (паттерны).
            Пример такого поискового запроса: ((00* OR 01*) NEAR/+10 прим*)
            -->
            <nearPatterns>

                <!--
                Максимальное допустимое количество термов, которое мы собираем в кеш по шаблонам
                поискового запроса со всей индексной базы за один поисковый запрос.
                Если будет превышен этот предел, результаты поискового запроса будут не полными.
                -->
                <maxTotalTermsCount>70000</maxTotalTermsCount>


                <!--
                Максимальная длина терма, разрешённая для поиска по префиксу из одного символа.
                Например, если максимальная длина терма равна 2 (двум), то, например, для запроса (1*)
                мы сможем найти такие числа как 10, 19, но уже не сможем найти трёхзначные числа и далее.
                Ограничения для префикса большей длины устанавливается по формуле:
                   maxTermLen_N = (prefixLen * 8) + (maxTermLenForSingleCharPrefix - 8);
                Если сюда установить 0 или отрицательное число, ограничение перестанет применяться
                для префиксов (включая шаблоны) любой длины.
                Поиск по префиксу - это поиск по шаблону типа (prefix*), другие типы шаблонов также
                чувствительны к этому параметру.
                -->
                <maxTermLenForSingleCharPrefix>7</maxTermLenForSingleCharPrefix>


                <!--
                Максимальная длина для шаблонов (паттернов), которые считаются жадными.
                Например, если длина префикса больше чем greedyPatternMaxLength,
                тогда для такого префикса не будут применяться алгоритмы оптимизации, фильтрации
                или накладываться какие-либо ограничения.

                Примеры жадных шаблонов и их условная длина:
                   а*   (len=1)
                   12*  (len=2)
                   *0   (len=1)
                   *12  (len=2)
                   *22* (len=2)
                   d?   (len=2)
                   d??  (len=2)
                   d*?? (len=2)
                -->
                <greedyPatternMaxLength>3</greedyPatternMaxLength>;

            </nearPatterns>

        </limits>

        <!-- Настройки для анализа поисковых запросов. -->
        <searchQuery>

            <!--
            Язык поисковых запросов. По языку выбирается соответствующий анализатор текста, который
            умеет выделять основу слова, выкидывать мусорные слова, пропускать ненужные знаки препинания.
            -->
            <language default="ru"/>

            <!-- Обработка пробела в поисковых запросах-->
            <space operator="AND"/>

            <!-- Описание алиасов для полей -->
            <aliases>
                <field id="content" aliases="СОДЕРЖИМОЕ; ОСНОВНОЕ; ТЕЛО; BODY"/>
                <field id="title"   aliases="ШАПКА; ЗАГЛ; ЗАГЛАВИЕ; TITLE"/>
            </aliases>

            <!-- Описание полей по которым ведётся поиск-->
            <fields default="content">
                <field id="content"/>
            </fields>

            <!-- Описание операторов и их значений по умолчанию -->
            <operators>

                <!-- Оператор усиления значимости -->
                <boost default="2"/>

                <!-- Оператор близости -->
                <near default="8"/>

                <!--
                Оператор нечёткого поиска
                fixedPrefix - длинна префикса у слова, в котором не будем искать изменения;
                -->
                <fuzzy default="1" fixedPrefix="0" />

            </operators>

            <!--Ограничения, пределы -->
            <limits>

                <!--
                Минимальная длина префикса для токена из букв (alphabetical).
                Этот параметр влияет на применение морфологии к словам из поискового запроса.
                Например, из слова "мыться" алгоритм не будет отрезать "ться" и искать
                по префиксу "мы*", если префикс короче minAlphaPrefixLen.
                -->
                <minAlphaPrefixLen>2</minAlphaPrefixLen>;

            </limits>

        </searchQuery>

        <!-- Разбиение на страницы результатов поиска. -->
        <paging>

            <!-- Сколько документов на одну страницу выдавать. -->
            <pageSize>100</pageSize>

        </paging>


        <!--
        Настройки результатов поиска
        -->
        <results>


            <!--
            Параметры для составления фрагмента - куска текста с подсветкой в нём найденных слов.
            -->
            <fragment>

                <!--
                Настройки для короткого фрагмента
                -->
                <short>

                    <!-- Максимальная длина одного фрагмента в символах. -->
                    <fragmentSize>110</fragmentSize>

                    <!-- Максимальное количество фрагментов текста, которое нужно генерировать по документу. -->
                    <maxNumFragments>2</maxNumFragments>

                    <!-- Заполнитель между разрывами текста, т.е. между фрагментами. -->
                    <delimiter>... </delimiter>

                    <!--
                    Подсветка слов посредством обрамления в теги.
                    -->
                    <highlighting>
                        <preTag><![CDATA[<b>]]></preTag>
                        <postTag><![CDATA[</b>]]></postTag>
                    </highlighting>

                </short>


                <!--
                Настройки для длинного фрагмента.
                -->
                <long>

                    <!-- Максимальная длина одного фрагмента в символах. -->
                    <fragmentSize>300</fragmentSize>

                    <!-- Максимальное количество фрагментов текста, которое нужно генерировать по документу. -->
                    <maxNumFragments>4</maxNumFragments>

                    <!-- Заполнитель между разрывами текста, т.е. между фрагментами. -->
                    <delimiter>... </delimiter>

                    <!--
                    Подсветка слов посредством обрамления в теги.
                    -->
                    <highlighting>
                        <preTag><![CDATA[<b>]]></preTag>
                        <postTag><![CDATA[</b>]]></postTag>
                    </highlighting>

                </long>

            </fragment>

        </results>

    </search>

</config>
