mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 08:04:45 +00:00
refactor: drop structural labels from FTS indexable content
The "title: ", "summary: ", "name: ", "Subject: ", "Option: " etc. prefixes
were tokenized into the single FTS content column as literal words, so every
event of a type matched bare terms like "title" or "summary" and the index
carried useless tokens — the same field-name pollution we avoid for JSON
kinds. The FTS table has one content column and search is plain-text MATCH,
so the labels enabled no fielded search; they were pure noise.
Index bare field values instead (listOfNotNull(...).joinToString("\n")),
which also drops the "null" token the older one-liners produced for absent
fields. Applied across all SearchableEvent implementations for consistency.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RFdWREvyvixRXnmNXNzmmN
This commit is contained in:
+1
-6
@@ -88,12 +88,7 @@ class MusicPlaylistEvent(
|
||||
if (address.kind == MusicTrackEvent.KIND) address else null
|
||||
}
|
||||
|
||||
override fun indexableContent(): String =
|
||||
buildString {
|
||||
append("title: ").append(title().orEmpty()).append('\n')
|
||||
description()?.let { append("description: ").append(it).append('\n') }
|
||||
append(content)
|
||||
}
|
||||
override fun indexableContent(): String = listOfNotNull(title(), description(), content).joinToString("\n")
|
||||
|
||||
companion object {
|
||||
const val KIND = 34139
|
||||
|
||||
+1
-7
@@ -59,13 +59,7 @@ class MusicTrackEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent(): String =
|
||||
buildString {
|
||||
append("title: ").append(title().orEmpty()).append('\n')
|
||||
append("artist: ").append(artist().orEmpty()).append('\n')
|
||||
album()?.let { append("album: ").append(it).append('\n') }
|
||||
append(content)
|
||||
}
|
||||
override fun indexableContent(): String = listOfNotNull(title(), artist(), album(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ class NipTextEvent(
|
||||
AddressHintProvider,
|
||||
IForkableEvent,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
override fun dTag() = tags.dTag()
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ class ZapPollEvent(
|
||||
override fun indexableContent() =
|
||||
buildString {
|
||||
append(content)
|
||||
pollOptionsArray().forEach { append("\nOption: ").append(it.descriptor) }
|
||||
pollOptionsArray().forEach { append('\n').append(it.descriptor) }
|
||||
}
|
||||
|
||||
override fun eventHints(): List<EventIdHint> {
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ class FeedDefinitionEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty()
|
||||
override fun indexableContent() = title().orEmpty()
|
||||
|
||||
fun title(): String? = tags.firstOrNull { it.size >= 2 && it[0] == "title" }?.get(1)
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class TextNoteEvent(
|
||||
PubKeyHintProvider,
|
||||
IForkableEvent,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "Subject: " + subject() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(subject(), content).joinToString("\n")
|
||||
|
||||
override fun eventHints(): List<EventIdHint> {
|
||||
val eHints = tags.mapNotNull(MarkedETag::parseAsHint)
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ class LongTextNoteEvent(
|
||||
PublishedAtProvider,
|
||||
RootScope,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title() + "\nsummary: " + summary() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), summary(), content).joinToString("\n")
|
||||
|
||||
override fun eventHints(): List<EventIdHint> {
|
||||
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ class EmojiPackEvent(
|
||||
sig: HexKey,
|
||||
) : PrivateTagArrayEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + titleOrName().orEmpty() + "\ndescription: " + description().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(titleOrName(), description(), content).joinToString("\n")
|
||||
|
||||
@Deprecated("NIP-51 has deprecated name. Use title instead", ReplaceWith("title()"))
|
||||
fun name() = tags.firstNotNullOfOrNull(NameTag::parse)
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ class GitIssueEvent(
|
||||
EventHintProvider,
|
||||
AddressHintProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "Subject: " + subject() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(subject(), content).joinToString("\n")
|
||||
|
||||
override fun eventHints(): List<EventIdHint> {
|
||||
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ class GitPullRequestEvent(
|
||||
EventHintProvider,
|
||||
AddressHintProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "Subject: " + subject().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(subject(), content).joinToString("\n")
|
||||
|
||||
override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint)
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class GitRepositoryEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "name: " + name().orEmpty() + "\ndescription: " + description().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(name(), description(), content).joinToString("\n")
|
||||
|
||||
fun name() = tags.firstNotNullOfOrNull(NameTag::parse)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class TorrentEvent(
|
||||
sig: HexKey,
|
||||
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ class CalendarDateSlotEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\nsummary: " + summary().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), summary(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag.Companion::parse)
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class CalendarTimeSlotEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\nsummary: " + summary().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), summary(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag.Companion::parse)
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ class CalendarEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class MeetingSpaceEvent(
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
PubKeyHintProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "room: " + room().orEmpty() + "\nsummary: " + summary().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(room(), summary(), content).joinToString("\n")
|
||||
|
||||
override fun pubKeyHints() = tags.mapNotNull(ParticipantTag::parseAsHint)
|
||||
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ class LiveActivitiesEvent(
|
||||
PubKeyHintProvider,
|
||||
LiveStreamLike,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\nsummary: " + summary().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), summary(), content).joinToString("\n")
|
||||
|
||||
override fun eventHints(): List<EventIdHint> {
|
||||
val pinnedEvents = pinned()
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ class BadgeDefinitionEvent(
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "name: " + name().orEmpty() + "\ndescription: " + description().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(name(), description(), content).joinToString("\n")
|
||||
|
||||
fun name() = tags.badgeName()
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class PictureEvent(
|
||||
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
@kotlinx.serialization.Transient
|
||||
@kotlin.jvm.Transient
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ abstract class AddressableVideoEvent(
|
||||
VideoEvent,
|
||||
RootScope,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
@kotlinx.serialization.Transient
|
||||
@kotlin.jvm.Transient
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ abstract class RegularVideoEvent(
|
||||
VideoEvent,
|
||||
RootScope,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
@kotlinx.serialization.Transient
|
||||
@kotlin.jvm.Transient
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ class CommunityDefinitionEvent(
|
||||
AddressHintProvider,
|
||||
PubKeyHintProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "name: " + name().orEmpty() + "\ndescription: " + description().orEmpty() + "\nrules: " + rules().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(name(), description(), rules(), content).joinToString("\n")
|
||||
|
||||
override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class GoalEvent(
|
||||
AddressHintProvider,
|
||||
PubKeyHintProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "summary: " + summary().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(summary(), content).joinToString("\n")
|
||||
|
||||
override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class ThreadEvent(
|
||||
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.title()
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ class HighlightEvent(
|
||||
AddressHintProvider,
|
||||
PubKeyHintProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "comment: " + comment() + "\ncontext: " + context() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(comment(), context(), content).joinToString("\n")
|
||||
|
||||
override fun eventHints(): List<EventIdHint> {
|
||||
val eHints = tags.mapNotNull(ETag::parseAsHint)
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class ClassifiedsEvent(
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
PublishedAtProvider,
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = "title: " + title().orEmpty() + "\nsummary: " + summary().orEmpty() + "\n" + content
|
||||
override fun indexableContent() = listOfNotNull(title(), summary(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
|
||||
+3
-3
@@ -105,9 +105,9 @@ class FsSearchTest {
|
||||
|
||||
val ftsRoot = root.resolve("idx/fts")
|
||||
val tokenDirs = ftsRoot.listDirectoryEntries().map { it.fileName.toString() }.toSet()
|
||||
// TextNoteEvent.indexableContent() prepends a "Subject: " prefix so
|
||||
// we get the content tokens plus the subject ones. What matters is
|
||||
// that each unique token yields exactly one entry under its dir.
|
||||
// This note has no subject, so indexableContent() is just the
|
||||
// content. What matters is that each unique token yields exactly
|
||||
// one entry under its dir.
|
||||
assertTrue("bitcoin" in tokenDirs)
|
||||
assertTrue("nostr" in tokenDirs)
|
||||
assertEquals(1, ftsRoot.resolve("bitcoin").listDirectoryEntries().size)
|
||||
|
||||
Reference in New Issue
Block a user