Индекс = имя таблицы: для файлов files_file (Wrapper.IndexName => Table),
есть tenant_id; контент документа — document.attachment.content
(WrapperWithDoc, ingest-attachment).
REST GET /api/2.0/files/@search/{query} — это только БД по имени
(fileDao.Search, SearchHandler.SearchFiles), ES не задействует.
Значит для контент-поиска нужен прямой ES.
Конфиг ES у сервера: ElasticSection host/port/scheme (дефолт localhost:9200). Снаружи :9200 не открыт (проверено); SSH в VM открыт
(127.0.0.1:32) → нужен туннель; либо expose. — инфра-шаг.
Реализация
file_es.go: esStore/esSearcher — прямой ES REST (stdlib net/http или
канонический github.com/elastic/go-elasticsearch/v8, выбрать по версии ES).
Search(SearchQuery) → запрос по title и document.attachment.content
(multi_match), фильтр tenant_id, _source id/title/folder_id, highlight для фрагмента. Возвращает []SearchHit с Entry (маппинг
id → files_file).
PR: #41
Ветка feat/es-search#37 · коммит 33b5c1e (base main).
Не мержу и не закрываю.
Доступ к ES (research, live) — блокера нет
ES живёт внутри VM OnlyOffice (onlyoffice-v2), слушает 127.0.0.1:9200; версия 7.16.3, cluster elasticsearch. Снаружи :9200 закрыт, SSH в VM открыт как 127.0.0.1:32.
Креды SSH VM уже на хосте (~/.ssh/id_ed25519, root@127.0.0.1:32).
ControlMaster=no / ControlPath=none обязательны — иначе forward уходит в
persistent master из ~/.ssh/config.
Индекс files_file (~39.8k док-в), _count ОК.
Факты live поправили формулировку issue: поля не tenant_id/folder_id,
а tenantId (integer) и folders[].folderId (строка). Контент — document.attachment.content; заполняется только для Office-форматов
(docx/xlsx/pptx), у PDF/txt, залитых через API, контента нет.
title analyzer whitespacecustom — режет по пробелам/lower-case, полное
имя файла = один токен. REST @search по-прежнему только по имени в БД.
Реализация
file_es.go: ESSearcher — прямой ES REST на stdlib net/http (без новых
зависимостей). Search(SearchQuery):
multi_match по title^2; при InContent + document.attachment.content;
фильтр tenantId (env ONLYOFFICE_TENANT) и folders.folderId;
Модель Entry/Kind/SearchHit/SearchQuery/Searcher — из F1 #35;
пока объявлена в file_es.go (F1 ещё не влит), при мерже переезжает в file_core.go — согласуем.
Конфиг: ONLYOFFICE_ES_URL, ONLYOFFICE_ES_INDEX (default files_file), ONLYOFFICE_TENANT. .env.example — только имена.
Integration file_es_integration_test.go (//go:build integration, skip без ONLYOFFICE_ES_URL): TestIntegrationESSearch — заливает временный xlsx
(уникальные токены в имени и в ячейке), ждёт асинхронной индексации, находит
по имени и по контенту, проверяет highlight и что name-only поиск не
находит content-токен, затем удаляет проект. PASS live (туннель).
go build ./... && go vet ./... && go test -race ./... — зелёные.
gitleaks — no leaks found. Секретов в коде нет.
Примечание: go vet -tags=integration ./... падает на чужом файле cmd/office/fetch/task_integration_test.go:60 (loader.TaskFields undefined) —
существует на main, к PR не относится.
Блокеры
Нет. ES доступен через SSH-туннель; на постоянку его можно завернуть в
systemd-юнит (как vado-vision-tunnel) — отдельная инфра-задача.
## F3 — отчёт: Elasticsearch-клиент поиска (имя + контент) + `oo search`
PR: https://git.produktor.io/eSlider/go-onlyoffice/pulls/41
Ветка `feat/es-search#37` · коммит `33b5c1e` (base `main`).
Не мержу и не закрываю.
### Доступ к ES (research, live) — блокера нет
- ES живёт **внутри VM** OnlyOffice (`onlyoffice-v2`), слушает
`127.0.0.1:9200`; **версия 7.16.3**, cluster `elasticsearch`. Снаружи
`:9200` закрыт, SSH в VM открыт как `127.0.0.1:32`.
- Креды SSH VM уже на хосте (`~/.ssh/id_ed25519`, root@127.0.0.1:32).
- Туннель проверен live:
```bash
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/ # 7.16.3
curl -s 'http://127.0.0.1:9200/_cat/indices?h=index,docs.count'
```
`ControlMaster=no / ControlPath=none` обязательны — иначе forward уходит в
persistent master из `~/.ssh/config`.
- Индекс `files_file` (~39.8k док-в), `_count` ОК.
- **Факты live поправили формулировку issue:** поля не `tenant_id`/`folder_id`,
а `tenantId` (integer) и `folders[].folderId` (строка). Контент —
`document.attachment.content`; заполняется **только для Office-форматов**
(docx/xlsx/pptx), у PDF/txt, залитых через API, контента нет.
- `title` analyzer `whitespacecustom` — режет по пробелам/lower-case, полное
имя файла = один токен. REST `@search` по-прежнему только по имени в БД.
### Реализация
- `file_es.go`: `ESSearcher` — прямой ES REST на stdlib `net/http` (без новых
зависимостей). `Search(SearchQuery)`:
- `multi_match` по `title^2`; при `InContent` + `document.attachment.content`;
- фильтр `tenantId` (env `ONLYOFFICE_TENANT`) и `folders.folderId`;
- `_source` id/title/folders, `highlight` (теги `<em>` срезаются);
- возвращает `[]SearchHit`; `Name() = "elasticsearch"`.
- Модель `Entry`/`Kind`/`SearchHit`/`SearchQuery`/`Searcher` — из F1 #35;
пока объявлена в `file_es.go` (F1 ещё не влит), при мерже переезжает в
`file_core.go` — согласуем.
- Конфиг: `ONLYOFFICE_ES_URL`, `ONLYOFFICE_ES_INDEX` (default `files_file`),
`ONLYOFFICE_TENANT`. `.env.example` — только имена.
- CLI `oo search <query> [--content] [--folder id] [--limit N] [--json]` —
тонкая обёртка через `printTable`/`printJSON`.
- `docs/elasticsearch.md`: устройство поиска, схема полей, туннель, env,
грабли (анализ title, контент только Office, async-индексация).
### Тесты (имена + PASS)
- Unit `file_es_test.go`: `TestESSearchRequestNameOnly`,
`TestESSearchRequestContentFields`, `TestESSearchRequestFiltersAndLimit`,
`TestNewESSearcherRequiresURL`, `TestNormalizeExtensions`,
`TestParseESSearchResponse`, `TestESSearchRequestJSONShape` — PASS.
- CLI `cmd/oo/search_test.go`:
`TestSearchCommandRegisteredWithFlags`,
`TestSearchWithoutESURLIsClearError` — PASS.
- Integration `file_es_integration_test.go` (`//go:build integration`, skip без
`ONLYOFFICE_ES_URL`): `TestIntegrationESSearch` — заливает временный xlsx
(уникальные токены в имени и в ячейке), ждёт асинхронной индексации, находит
по имени и по контенту, проверяет highlight и что name-only поиск не
находит content-токен, затем удаляет проект. **PASS live** (туннель).
- `go build ./... && go vet ./... && go test -race ./...` — зелёные.
gitleaks — `no leaks found`. Секретов в коде нет.
Примечание: `go vet -tags=integration ./...` падает на **чужом** файле
`cmd/office/fetch/task_integration_test.go:60` (`loader.TaskFields undefined`) —
существует на `main`, к PR не относится.
### Блокеры
Нет. ES доступен через SSH-туннель; на постоянку его можно завернуть в
systemd-юнит (как `vado-vision-tunnel`) — отдельная инфра-задача.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Epic: #34
F3 — Elasticsearch-клиент поиска (имя + содержимое) +
oo searchЧто выяснено (research в исходниках CommunityServer)
NEST.files_file(Wrapper.IndexName => Table),есть
tenant_id; контент документа —document.attachment.content(
WrapperWithDoc, ingest-attachment).GET /api/2.0/files/@search/{query}— это только БД по имени(
fileDao.Search,SearchHandler.SearchFiles), ES не задействует.Значит для контент-поиска нужен прямой ES.
ElasticSectionhost/port/scheme (дефолтlocalhost:9200). Снаружи:9200не открыт (проверено); SSH в VM открыт(
127.0.0.1:32) → нужен туннель; либо expose. — инфра-шаг.Реализация
file_es.go:esStore/esSearcher— прямой ES REST (stdlibnet/httpиликанонический
github.com/elastic/go-elasticsearch/v8, выбрать по версии ES).Search(SearchQuery)→ запрос поtitleиdocument.attachment.content(
multi_match), фильтрtenant_id,_sourceid/title/folder_id,highlightдля фрагмента. Возвращает[]SearchHitсEntry(маппингid →
files_file).Name() = "elasticsearch".ONLYOFFICE_ES_URL(scheme+host+port),ONLYOFFICE_ES_INDEX(default
files_file),ONLYOFFICE_TENANT.oo search <query> [--content] [--folder id] [--json]— тонкая обёртка.127.0.0.1:32) или expose:9200; задокументировать.Тесты/критерии
//go:build integration, skip безONLYOFFICE_ES_URL):поиск по имени и по содержимому находит заранее залитый тестовый файл.
oo searchработает и уважает--output json.go build/vet/testзелёные; секретов нет.F3 — отчёт: Elasticsearch-клиент поиска (имя + контент) +
oo searchPR: #41
Ветка
feat/es-search#37· коммит33b5c1e(basemain).Не мержу и не закрываю.
Доступ к ES (research, live) — блокера нет
onlyoffice-v2), слушает127.0.0.1:9200; версия 7.16.3, clusterelasticsearch. Снаружи:9200закрыт, SSH в VM открыт как127.0.0.1:32.~/.ssh/id_ed25519, root@127.0.0.1:32).ControlMaster=no / ControlPath=noneобязательны — иначе forward уходит вpersistent master из
~/.ssh/config.files_file(~39.8k док-в),_countОК.tenant_id/folder_id,а
tenantId(integer) иfolders[].folderId(строка). Контент —document.attachment.content; заполняется только для Office-форматов(docx/xlsx/pptx), у PDF/txt, залитых через API, контента нет.
titleanalyzerwhitespacecustom— режет по пробелам/lower-case, полноеимя файла = один токен. REST
@searchпо-прежнему только по имени в БД.Реализация
file_es.go:ESSearcher— прямой ES REST на stdlibnet/http(без новыхзависимостей).
Search(SearchQuery):multi_matchпоtitle^2; приInContent+document.attachment.content;tenantId(envONLYOFFICE_TENANT) иfolders.folderId;_sourceid/title/folders,highlight(теги<em>срезаются);[]SearchHit;Name() = "elasticsearch".Entry/Kind/SearchHit/SearchQuery/Searcher— из F1 #35;пока объявлена в
file_es.go(F1 ещё не влит), при мерже переезжает вfile_core.go— согласуем.ONLYOFFICE_ES_URL,ONLYOFFICE_ES_INDEX(defaultfiles_file),ONLYOFFICE_TENANT..env.example— только имена.oo search <query> [--content] [--folder id] [--limit N] [--json]—тонкая обёртка через
printTable/printJSON.docs/elasticsearch.md: устройство поиска, схема полей, туннель, env,грабли (анализ title, контент только Office, async-индексация).
Тесты (имена + PASS)
file_es_test.go:TestESSearchRequestNameOnly,TestESSearchRequestContentFields,TestESSearchRequestFiltersAndLimit,TestNewESSearcherRequiresURL,TestNormalizeExtensions,TestParseESSearchResponse,TestESSearchRequestJSONShape— PASS.cmd/oo/search_test.go:TestSearchCommandRegisteredWithFlags,TestSearchWithoutESURLIsClearError— PASS.file_es_integration_test.go(//go:build integration, skip безONLYOFFICE_ES_URL):TestIntegrationESSearch— заливает временный xlsx(уникальные токены в имени и в ячейке), ждёт асинхронной индексации, находит
по имени и по контенту, проверяет highlight и что name-only поиск не
находит content-токен, затем удаляет проект. PASS live (туннель).
go build ./... && go vet ./... && go test -race ./...— зелёные.gitleaks —
no leaks found. Секретов в коде нет.Примечание:
go vet -tags=integration ./...падает на чужом файлеcmd/office/fetch/task_integration_test.go:60(loader.TaskFields undefined) —существует на
main, к PR не относится.Блокеры
Нет. ES доступен через SSH-туннель; на постоянку его можно завернуть в
systemd-юнит (как
vado-vision-tunnel) — отдельная инфра-задача.