Index all notes at start

This commit is contained in:
Hubert Van De Walle 2020-08-19 16:45:55 +02:00
parent ab3766b8b8
commit 12619f6550
10 changed files with 60 additions and 2 deletions

3
.gitignore vendored
View File

@ -130,3 +130,6 @@ app/src/main/resources/static/styles*
# h2 db
*.db
# lucene index
.lucene/

View File

@ -14,8 +14,10 @@ import be.simplenotes.app.views.NoteView
import be.simplenotes.app.views.SettingView
import be.simplenotes.app.views.UserView
import be.simplenotes.domain.domainModule
import be.simplenotes.domain.usecases.NoteService
import be.simplenotes.persistance.DbMigrations
import be.simplenotes.persistance.persistanceModule
import be.simplenotes.search.searchModule
import be.simplenotes.shared.config.DataSourceConfig
import be.simplenotes.shared.config.JwtConfig
import org.http4k.core.RequestContexts
@ -36,6 +38,7 @@ fun main() {
baseModule,
noteModule,
settingsModule,
searchModule,
)
}.koin
@ -50,6 +53,9 @@ fun main() {
val migrations = koin.get<DbMigrations>()
migrations.migrate()
val noteService = koin.get<NoteService>()
noteService.indexAll()
koin.get<Server>().start()
}

View File

@ -26,7 +26,7 @@ val domainModule = module {
single<PasswordHash> { BcryptPasswordHash() }
single { SimpleJwt(get()) }
single { JwtPayloadExtractor(get()) }
single { NoteService(get(), get(), get()) }
single { NoteService(get(), get(), get(), get()) }
single<MarkdownConverter> { MarkdownConverterImpl() }
single<ExportUseCase> { ExportUseCaseImpl(get()) }
}

View File

@ -9,12 +9,14 @@ import be.simplenotes.domain.security.HtmlSanitizer
import be.simplenotes.domain.usecases.markdown.MarkdownConverter
import be.simplenotes.domain.usecases.markdown.MarkdownParsingError
import be.simplenotes.domain.usecases.repositories.NoteRepository
import be.simplenotes.domain.usecases.repositories.UserRepository
import be.simplenotes.search.NoteSearcher
import java.util.*
class NoteService(
private val markdownConverter: MarkdownConverter,
private val noteRepository: NoteRepository,
private val userRepository: UserRepository,
private val searcher: NoteSearcher,
) {
@ -74,6 +76,13 @@ class NoteService(
fun countDeleted(userId: Int) = noteRepository.count(userId, deleted = true)
fun indexAll() {
val userIds = userRepository.findAll()
userIds.forEach { id ->
val notes = noteRepository.findAllDetails(id)
searcher.indexNotes(id, notes)
}
}
}
data class PaginatedNotes(val pages: Int, val notes: List<PersistedNoteMetadata>)

View File

@ -27,4 +27,5 @@ interface NoteRepository {
fun find(userId: Int, uuid: UUID): PersistedNote?
fun update(userId: Int, uuid: UUID, note: Note): PersistedNote?
fun export(userId: Int): List<ExportedNote>
fun findAllDetails(userId: Int): List<PersistedNote>
}

View File

@ -10,4 +10,5 @@ interface UserRepository {
fun exists(username: String): Boolean
fun exists(id: Int): Boolean
fun delete(id: Int): Boolean
fun findAll(): List<Int>
}

View File

@ -197,4 +197,25 @@ internal class NoteRepositoryImpl(private val db: Database) : NoteRepository {
)
}
}
override fun findAllDetails(userId: Int): List<PersistedNote> {
val notes = db.notes
.filterColumns { it.columns - it.deleted }
.filter { (it.userId eq userId) and (it.deleted eq false) }
.toList()
if (notes.isEmpty()) return emptyList()
val uuids = notes.map { note -> note.uuid }
val tagsByUuid = db.tags
.filterColumns { listOf(it.noteUuid, it.name) }
.filter { it.noteUuid inList uuids }
.groupByTo(HashMap(), { it.note.uuid }, { it.name })
return notes.map { note ->
val tags = tagsByUuid[note.uuid] ?: emptyList()
note.toPersistedNote(tags)
}
}
}

View File

@ -28,4 +28,5 @@ internal class UserRepositoryImpl(private val db: Database) : UserRepository {
override fun exists(username: String) = db.users.any { it.username eq username }
override fun exists(id: Int) = db.users.any { it.id eq id }
override fun delete(id: Int) = db.useTransaction { db.delete(Users) { it.id eq id } == 1 }
override fun findAll() = db.from(Users).select(Users.id).map { it[Users.id]!! }
}

View File

@ -52,6 +52,21 @@ class NoteSearcher(basePath: Path = Path.of("/tmp", "lucene")) {
}
}
fun indexNotes(userId: Int, notes: List<PersistedNote>) {
logger.debug("Indexing notes for user $userId")
val dir = getDirectory(userId)
val config = IndexWriterConfig(StandardAnalyzer())
val writer = IndexWriter(dir, config)
val docs = notes.map { it.toDocument() }
with(writer) {
addDocuments(docs)
commit()
close()
}
}
fun deleteIndex(userId: Int, uuid: UUID) {
logger.debug("Deleting indexing $uuid for user $userId")

View File

@ -1,7 +1,8 @@
package be.simplenotes.search
import org.koin.dsl.module
import java.nio.file.Path
val searchModule = module {
single { NoteSearcher() }
single { NoteSearcher(Path.of(".lucene")) }
}