Extend free-text search (q) to also match payload
All checks were successful
Build and Deploy iObj / build-image (push) Successful in 36s

Cross-shard search already worked transparently across all monthly
JSON files. This adds payload content (e.g. commit SHA, meeting
attendees, structured data) to the q= substring match, alongside
title and body.
This commit is contained in:
2026-07-13 21:57:45 +02:00
parent 10e98e1bdc
commit dc45e825c9
3 changed files with 16 additions and 2 deletions

View File

@@ -57,7 +57,7 @@ Alle `/objects*` endpoints kræver `Authorization: Bearer <IOBJ_API_TOKEN>`
|---|---|---|
| GET | `/health` | Liveness check |
| POST | `/objects` | Opret objekt |
| GET | `/objects` | Søg (query params: `type`, `project`, `tag`, `date_from`, `date_to`, `q`, `limit`, `offset`) |
| GET | `/objects` | Søg (query params: `type`, `project`, `tag`, `date_from`, `date_to`, `q`, `limit`, `offset`). `q` matcher fritekst i `title`, `body` og `payload`. |
| GET | `/objects/date/{date}` | Alle objekter for én dato |
| GET | `/objects/{id}` | Hent ét objekt |
| PATCH | `/objects/{id}` | Opdater (delvist) |

View File

@@ -7,6 +7,7 @@ possibly contain matches for a given date range.
"""
from __future__ import annotations
import json
import re
import threading
from datetime import date, datetime
@@ -172,7 +173,8 @@ def _matches(obj: MemoryObject, query: SearchQuery) -> bool:
return False
if query.q:
needle = query.q.lower()
haystack = f"{obj.title}\n{obj.body}".lower()
payload_text = json.dumps(obj.payload, ensure_ascii=False, default=str) if obj.payload else ""
haystack = f"{obj.title}\n{obj.body}\n{payload_text}".lower()
if needle not in haystack:
return False
return True

View File

@@ -119,6 +119,18 @@ def test_search_free_text_matches_title_and_body(store):
assert len(results) == 2
def test_search_free_text_matches_payload(store):
store.create(_mk(title="commit", payload={"sha": "abc123def", "author": "Henrik Jess"}))
store.create(_mk(title="other commit", payload={"sha": "zzz999", "author": "Someone Else"}))
results = store.search(SearchQuery(q="abc123def"))
assert len(results) == 1
assert results[0].title == "commit"
results = store.search(SearchQuery(q="henrik"))
assert len(results) == 1
assert results[0].title == "commit"
def test_search_respects_limit_and_offset_and_sort_order(store):
for i in range(5):
store.create(_mk(object_date=date(2026, 1, 1 + i), title=f"obj{i}"))