126 lines
5.3 KiB
Markdown
126 lines
5.3 KiB
Markdown
---
|
||
type: reference
|
||
status: current
|
||
related:
|
||
- README.md
|
||
- file_es.go
|
||
---
|
||
|
||
# Elasticsearch — полнотекстовый поиск OnlyOffice
|
||
|
||
## Что это
|
||
|
||
Полнотекстовый поиск OnlyOffice Workspace работает на **Elasticsearch**.
|
||
Клиент на сервере — NEST. Индекс — имя таблицы.
|
||
|
||
Для файлов индекс `files_file`:
|
||
|
||
| поле | тип | смысл |
|
||
|------|-----|-------|
|
||
| `id` | integer | id файла (тот же, что в REST/Documents) |
|
||
| `title` | text (`whitespacecustom`) | имя файла |
|
||
| `tenantId` | integer | тенант (портал) |
|
||
| `folders` | nested | список папок: `folderId` (строка), `id`, `tenantId` |
|
||
| `document.attachment.content` | text (`document`) | извлеченный текст (ingest-attachment) |
|
||
| `document.attachment.content_type` | text | MIME |
|
||
|
||
Важно:
|
||
- Живой сервер — **Elasticsearch 7.16.3**, кластер `elasticsearch`.
|
||
- REST `GET /api/2.0/files/@search/{query}` ищет **только по имени в БД**
|
||
(`fileDao.Search`), ES не задействует. Для поиска по содержимому нужен
|
||
прямой ES — это и делает `oo search`.
|
||
- `title` analyzer `whitespacecustom` режет по пробелам и lower-case. Полное
|
||
имя файла — один токен (`Rechnung-4711.pdf`), поэтому поиск по имени ищет
|
||
слово целиком, а не подстроку.
|
||
- `document.attachment.content` заполняется **только для Office-форматов**
|
||
(docx / xlsx / pptx). У PDF/txt, залитых через API, контент не извлекается.
|
||
- Индексация асинхронная (TeamLabSvc) — файл появляется в ES не мгновенно.
|
||
|
||
## Доступ
|
||
|
||
ES слушает `127.0.0.1:9200` **внутри** VM OnlyOffice. Снаружи порт закрыт,
|
||
SSH в VM открыт на хосте как `127.0.0.1:32` (контейнер `onlyoffice-v2`,
|
||
QEMU). Схема — SSH-туннель.
|
||
|
||
```bash
|
||
# из корня go-onlyoffice (ключ и хост — как в infra-доках)
|
||
ssh -f -N -o ControlMaster=no -o ControlPath=none \
|
||
-p 32 -i ~/.ssh/id_ed25519 \
|
||
-L 9200:127.0.0.1:9200 root@127.0.0.1
|
||
|
||
curl -s http://127.0.0.1:9200/ | head # tagline + version
|
||
curl -s 'http://127.0.0.1:9200/_cat/indices?h=index,docs.count'
|
||
```
|
||
|
||
`-o ControlMaster=no -o ControlPath=none` обязательны: иначе forward уходит
|
||
в persistent master-соединение из `~/.ssh/config` и порт остаётся занят.
|
||
|
||
Проверить, что туннель жив:
|
||
|
||
```bash
|
||
curl -s http://127.0.0.1:9200/files_file/_count
|
||
```
|
||
|
||
## Переменные
|
||
|
||
| env | default | смысл |
|
||
|-----|---------|-------|
|
||
| `ONLYOFFICE_ES_URL` | — (обязателен) | `scheme://host:port` ES |
|
||
| `ONLYOFFICE_ES_INDEX` | `files_file` | индекс |
|
||
| `ONLYOFFICE_TENANT` | пусто (все) | фильтр `tenantId` |
|
||
|
||
Имена — в [`.env.example`](../.env.example). Секретов нет: ES без пароля.
|
||
|
||
## CLI
|
||
|
||
```bash
|
||
ONLYOFFICE_ES_URL=http://127.0.0.1:9200 oo search "Rechnung"
|
||
ONLYOFFICE_ES_URL=http://127.0.0.1:9200 oo search "Mahngebühr" --content
|
||
oo search "Rechnung" --folder 649 --limit 50 --json
|
||
```
|
||
|
||
Флаги: `--content` (искать и по тексту), `--folder ID` (папка
|
||
`folders.folderId`), `--limit N` (по умолчанию 20, максимум 200),
|
||
`--json` = `-o json`.
|
||
|
||
## Библиотека
|
||
|
||
`file_es.go` — `ESSearcher` (`Name() = "elasticsearch"`), прямой ES REST на
|
||
stdlib `net/http`:
|
||
|
||
```go
|
||
es, _ := onlyoffice.NewESSearcher(onlyoffice.ESConfigFromEnv())
|
||
hits, _ := es.Search(ctx, onlyoffice.SearchQuery{
|
||
Text: "Rechnung", InContent: true, Limit: 20,
|
||
})
|
||
```
|
||
|
||
Запрос: `multi_match` по `title^2` (+ `document.attachment.content` при
|
||
`InContent`), фильтры `tenantId` и `folders.folderId`, `_source`
|
||
id/title/folders, `highlight` для фрагмента. Ответ → `[]SearchHit` (модель из
|
||
эпика #34; пока объявлена в `file_es.go`, переедет в `file_core.go` с F1 #35).
|
||
|
||
## Тесты
|
||
|
||
```bash
|
||
# unit — чистые builders/парсеры, без сети
|
||
go test ./ -run ES
|
||
|
||
# integration — нужен ONLYOFFICE_ES_URL (+ креды REST для залива)
|
||
set -a; . .env; set +a
|
||
ONLYOFFICE_ES_URL=http://127.0.0.1:9200 ONLYOFFICE_TENANT=1 \
|
||
go test -tags=integration -run TestIntegrationESSearch -v .
|
||
```
|
||
|
||
Интеграционный тест заливает временный xlsx (в имени и в ячейке — уникальные
|
||
токены), ждёт индексации, проверяет поиск по имени и по содержимому, затем
|
||
удаляет проект.
|
||
|
||
## Грабли
|
||
|
||
- `locale`/версия ES: 7.16.3, `_search` совместим с REST 7.x.
|
||
- ES без auth и слушает только localhost — туннель обязателен.
|
||
- Фильтр `tenantId` сузит выдачу; без него видны документы всех тенантов.
|
||
- Поиск по содержимому PDF, залитых через API, не работает (нет
|
||
`attachment.content`) — только Office-форматы.
|