Skip to content

Commit 54897d8

Browse files
authored
Merge pull request #36 from Paulanerus/dev
Dev
2 parents fc0c840 + eea5c65 commit 54897d8

3 files changed

Lines changed: 37 additions & 47 deletions

File tree

core/src/main/kotlin/dev/paulee/core/data/analysis/Indexer.kt

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ import dev.paulee.api.data.Language
55
import dev.paulee.api.data.Source
66
import dev.paulee.api.data.UniqueField
77
import dev.paulee.core.normalizeDataSource
8-
import dev.paulee.core.splitStr
98
import org.apache.lucene.analysis.Analyzer
109
import org.apache.lucene.analysis.core.WhitespaceAnalyzer
11-
import org.apache.lucene.analysis.en.EnglishAnalyzer
1210
import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper
1311
import org.apache.lucene.document.Document
1412
import org.apache.lucene.document.Field
@@ -18,25 +16,33 @@ import org.apache.lucene.index.DirectoryReader
1816
import org.apache.lucene.index.IndexWriter
1917
import org.apache.lucene.index.IndexWriterConfig
2018
import org.apache.lucene.index.Term
21-
import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser
22-
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler
23-
import org.apache.lucene.search.BooleanClause
24-
import org.apache.lucene.search.BooleanQuery
19+
import org.apache.lucene.queryparser.classic.QueryParser
2520
import org.apache.lucene.search.IndexSearcher
26-
import org.apache.lucene.search.PhraseQuery
27-
import org.apache.lucene.search.TermQuery
21+
import org.apache.lucene.search.Query
2822
import org.apache.lucene.store.BaseDirectory
2923
import org.apache.lucene.store.FSDirectory
3024
import org.apache.lucene.store.NIOFSDirectory
3125
import org.slf4j.LoggerFactory.getLogger
3226
import java.io.Closeable
3327
import java.nio.file.Path
3428

35-
class Indexer(path: Path, sources: List<Source>) : Closeable {
29+
internal class CustomParser(private val defaultField: String, defaultAnalyzer: Analyzer) :
30+
QueryParser(defaultField, defaultAnalyzer) {
31+
32+
override fun newFieldQuery(
33+
analyzer: Analyzer,
34+
field: String?,
35+
queryText: String?,
36+
quoted: Boolean,
37+
): Query {
38+
val target = if (quoted) "$defaultField.ws" else (field ?: defaultField)
39+
return super.newFieldQuery(analyzer, target, queryText, quoted)
40+
}
41+
}
3642

37-
companion object {
38-
private val QUOTE_REGEX = Regex("\"([^\"]+?)\"")
43+
internal class Indexer(path: Path, sources: List<Source>) : Closeable {
3944

45+
companion object {
4046
private val OPERATOR_CASCADE_REGEX =
4147
Regex("(?i)\\b(AND(?:\\s+NOT)?|OR(?:\\s+NOT)?|NOT)\\b(?:\\s+(?:AND|OR|NOT)\\b)*")
4248

@@ -125,11 +131,7 @@ class Indexer(path: Path, sources: List<Source>) : Closeable {
125131
}
126132

127133
fun searchFieldIndex(field: String, query: String): List<Document> {
128-
val exactTerms = QUOTE_REGEX.findAll(query).map { it.groupValues[1] }.toList()
129-
130-
val stripped = query.replace(QUOTE_REGEX, "").trim()
131-
132-
val normalized = normalizeOperator(stripped)
134+
val normalized = normalizeOperator(query)
133135

134136
DirectoryReader.openIfChanged(this.reader)?.let {
135137
this.reader.close()
@@ -139,32 +141,20 @@ class Indexer(path: Path, sources: List<Source>) : Closeable {
139141

140142
val searcher = IndexSearcher(this.reader)
141143

142-
val queryBuilder = BooleanQuery.Builder()
144+
val perField =
145+
PerFieldAnalyzerWrapper(
146+
mappedAnalyzer[field] ?: LangAnalyzer.new(Language.ENGLISH),
147+
mappedAnalyzer
148+
)
143149

144-
if (normalized.isNotBlank()) {
145-
val parser = StandardQueryParser(mappedAnalyzer[field] ?: EnglishAnalyzer()).apply {
146-
defaultOperator = StandardQueryConfigHandler.Operator.AND
147-
allowLeadingWildcard = true
148-
}
149-
150-
queryBuilder.add(parser.parse(normalized, field), BooleanClause.Occur.MUST)
150+
val parser = CustomParser(field, perField).apply {
151+
defaultOperator = QueryParser.Operator.AND
152+
allowLeadingWildcard = true
151153
}
152154

153-
exactTerms.map { splitStr(it, ' ') }.forEach { rawTerm ->
154-
if (rawTerm.isEmpty()) return@forEach
155-
156-
if (rawTerm.size == 1) {
157-
queryBuilder.add(TermQuery(Term("$field.ws", rawTerm[0])), BooleanClause.Occur.MUST)
158-
} else {
159-
val phraseBuilder = PhraseQuery.Builder()
160-
161-
rawTerm.forEach { phraseBuilder.add(Term("$field.ws", it)) }
162-
163-
queryBuilder.add(phraseBuilder.build(), BooleanClause.Occur.MUST)
164-
}
165-
}
155+
val query = parser.parse(normalized)
166156

167-
val hits = searcher.search(queryBuilder.build(), Int.MAX_VALUE)
157+
val hits = searcher.search(query, Int.MAX_VALUE)
168158
return hits.scoreDocs.map { searcher.storedFields().document(it.doc) }
169159
}
170160

gradle.properties

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
22
kotlin.code.style=official
33
kotlin.version=2.2.0
4-
compose.version=1.8.0
4+
compose.version=1.8.2
55
icons.version=1.7.3
6-
lucene.version=10.2.1
7-
log4j.version=2.24.3
8-
jackson.version=2.19.0
9-
sqlite-jdbc.version=3.49.1.0
6+
lucene.version=10.2.2
7+
log4j.version=2.25.1
8+
jackson.version=2.19.2
9+
sqlite-jdbc.version=3.50.3.0
1010
jdu.version=4.15
1111
coroutines.version=1.10.2
1212

1313
api.version=1.9.0
14-
core.version=1.11.1
15-
ui.version=1.10.0
16-
app.version=1.3.0
14+
core.version=1.11.2
15+
ui.version=1.10.1
16+
app.version=1.3.1

ui/src/main/kotlin/dev/paulee/ui/TextExplorerUI.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ class TextExplorerUI(
272272
suppressNextEnterSearch = false
273273
return@onPreviewKeyEvent true
274274
}
275-
if (textField.text.isNotBlank()) {
275+
if (textField.text.isNotBlank() && dataService.hasSelectedPool()) {
276276
performSearch()
277277
return@onPreviewKeyEvent true
278278
}

0 commit comments

Comments
 (0)