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

View File

@ -26,7 +26,7 @@ val domainModule = module {
single<PasswordHash> { BcryptPasswordHash() } single<PasswordHash> { BcryptPasswordHash() }
single { SimpleJwt(get()) } single { SimpleJwt(get()) }
single { JwtPayloadExtractor(get()) } single { JwtPayloadExtractor(get()) }
single { NoteService(get(), get(), get()) } single { NoteService(get(), get(), get(), get()) }
single<MarkdownConverter> { MarkdownConverterImpl() } single<MarkdownConverter> { MarkdownConverterImpl() }
single<ExportUseCase> { ExportUseCaseImpl(get()) } 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.MarkdownConverter
import be.simplenotes.domain.usecases.markdown.MarkdownParsingError import be.simplenotes.domain.usecases.markdown.MarkdownParsingError
import be.simplenotes.domain.usecases.repositories.NoteRepository import be.simplenotes.domain.usecases.repositories.NoteRepository
import be.simplenotes.domain.usecases.repositories.UserRepository
import be.simplenotes.search.NoteSearcher import be.simplenotes.search.NoteSearcher
import java.util.* import java.util.*
class NoteService( class NoteService(
private val markdownConverter: MarkdownConverter, private val markdownConverter: MarkdownConverter,
private val noteRepository: NoteRepository, private val noteRepository: NoteRepository,
private val userRepository: UserRepository,
private val searcher: NoteSearcher, private val searcher: NoteSearcher,
) { ) {
@ -74,6 +76,13 @@ class NoteService(
fun countDeleted(userId: Int) = noteRepository.count(userId, deleted = true) 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>) 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 find(userId: Int, uuid: UUID): PersistedNote?
fun update(userId: Int, uuid: UUID, note: Note): PersistedNote? fun update(userId: Int, uuid: UUID, note: Note): PersistedNote?
fun export(userId: Int): List<ExportedNote> 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(username: String): Boolean
fun exists(id: Int): Boolean fun exists(id: Int): Boolean
fun delete(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(username: String) = db.users.any { it.username eq username }
override fun exists(id: Int) = db.users.any { it.id eq id } 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 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) { fun deleteIndex(userId: Int, uuid: UUID) {
logger.debug("Deleting indexing $uuid for user $userId") logger.debug("Deleting indexing $uuid for user $userId")

View File

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