Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lucene search backend #8963

Draft
wants to merge 111 commits into
base: main
Choose a base branch
from
Draft

Lucene search backend #8963

wants to merge 111 commits into from

Conversation

btut
Copy link
Contributor

@btut btut commented Jul 9, 2022

First draft of the switch to the Lucene Search Backend

Whats working

  • Added all bib-fields to the index
  • BibEntry hash is used as an identifier in the index
  • Both fulltext and bib-fields are indexed together, in the same index, in the background. BibEntry-fields changes are prioritized as they are very quick.
  • Can see in the code that searches in bib-fields are working as expected
  • Switch current search to use the lucene backend
  • Sort search-results by lucene score. This means search will not filter the table anymore, but merely sort according to results
  • Global search (in contrast to main table, the global search window filters for matches with score > 0)
  • Change the file button-icon depending on whether there was a fulltext-search match for this entry
  • Search-Groups
  • Floating search
  • Switch to force sort by score or not

Todo

  • Remove old search
  • Display x.y at score only (two decimal places)
    • The cell itself should be colored. From green to red (all in light shade): 10=green, 0= red
  • Decide whether to display score column. Currently, it shows when a search is active. Users probably cannot do anything with the values, though. Maybe use it to shade entries with high relevance?
    • --> We keep the score column
  • Use gray background for score==0. See Issues with search and groups and associated feature request (floating mode) #4237 (comment).
    • Scroll to top until hits are shown (scroll down 1 shows a gray line)

Follow-ups

  • Improve fulltext-search-results display
    • A little improvement was already done. The file icon in the table is now different (shows a magnifying glass) when there were search results in a linked file.
    • Could be improved even more by inserting a fulltext-results row below the actual row.
  • Improve query-entry (like Prototype Implement better Search #341 #8356?)

Problems:

  • The score-column is always used to sort the table as highest-priority. JabRef will only sort by two columns max. This means with the search-score being one of them, users can only sort by one column.
    • Solution: add sort-columns with shift-click
    • Solution: Sorting by score column is not forced but optional
  • Everything is indexed with the JabRef field names, which are in English. This means, either we translate the fields when creating an index, or people need to use the english terms for search queries. Translating the fields in english would mean a re-index needs to be triggered whenever the language changes and JabRef would need to notice if the language changed while it was closed.
    • Solution: leave as-is, search-syntax is English and was English before the migration to lucene
  • Search group migration.

Fixes #8857
Peek 2022-08-17 20-01

  • Change in CHANGELOG.md described in a way that is understandable for the average user (if applicable)
  • Tests created for changes (if applicable)
  • Manually tested changed features in running JabRef (always required)
  • Screenshots added in PR description (for UI changes)
  • Checked developer's documentation: Is the information available and up to date? If not, I outlined it in this pull request.
  • Checked documentation: Is the information available and up to date? If not, I created an issue at https://github.com/JabRef/user-documentation/issues or, even better, I submitted a pull request to the documentation repository.

@koppor koppor changed the base branch from main to version6 July 9, 2022 18:27
@koppor koppor added this to the v6.0 milestone Jul 9, 2022
@ThiloteE ThiloteE added the search label Jul 9, 2022
Comment on lines 92 to 97
HashMap<String, Float> boosts = new HashMap<String, Float>();
SearchFieldConstants.searchableBibFields.stream().forEach(field -> boosts.put(field, Float.valueOf(4)));

if (query.getSearchFlags().contains(SearchRules.SearchFlags.FULLTEXT)) {
Arrays.stream(SearchFieldConstants.PDF_FIELDS).forEach(field -> boosts.put(field, Float.valueOf(1)));
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easy, but ugly. Maybe define a boost property for the standard Fields and get that by Field-name?

@tobiasdiez
Copy link
Member

Very nice to see this implemented! A few comments from my side:

  • I wouldn't bother with the migration of search groups. There is going to be friction anyway if users use advanced search functionality. Maybe show a info message if the Bib file contains search groups saying that those groups might not work as expected and need to be migrated manually?
  • What about showing the search score as a graphic similar to the battery or signal icon on the phone?
  • I have not yet tested this version, but I am a bit sceptical about implementing the search via sorting instead of filtering. I suspect that the search score will differ slightly between similar entries and thus the secondary sorting by the user will have no impact. A particular use case: Find all works by a certain author and sort them according to the read status column.
  • I'm definitely a big fan of adding the search score as a column, but would leave it to the user to sort the results according to the score.

@btut
Copy link
Contributor Author

btut commented Jul 22, 2022

Very nice to see this implemented! A few comments from my side:

  • I wouldn't bother with the migration of search groups. There is going to be friction anyway if users use advanced search functionality. Maybe show a info message if the Bib file contains search groups saying that those groups might not work as expected and need to be migrated manually?

Would definitely reduce coding effort and migration code.

  • What about showing the search score as a graphic similar to the battery or signal icon on the phone?

Thought about that too, maybe with the option for power-users to show floats instead. I am very bad at UI design though, did not get good feedback whenever I implemented something, so would need some help with that.

  • I have not yet tested this version, but I am a bit sceptical about implementing the search via sorting instead of filtering. I suspect that the search score will differ slightly between similar entries and thus the secondary sorting by the user will have no impact. A particular use case: Find all works by a certain author and sort them according to the read status column.

Thats true, but filtering kind of defeats the purpose of a fulltext/fuzzy search IMO. Where do you draw the line for the filtering predicate? Score==0? In large libraries that will result in a table with lots of "bad" search results with scores slightly above 0 and people could need to scroll to find much better matches.

  • I'm definitely a big fan of adding the search score as a column, but would leave it to the user to sort the results according to the score.

In any case, we would need to have a very nice way to display the score if we do not sort on it, so users can still tell better fits apart.

# Conflicts:
#	CHANGELOG.md
#	src/jmh/java/org/jabref/benchmarks/Benchmarks.java
#	src/main/java/org/jabref/gui/JabRefFrame.java
#	src/main/java/org/jabref/gui/LibraryTab.java
#	src/main/java/org/jabref/gui/entryeditor/EntryEditor.java
#	src/main/java/org/jabref/gui/entryeditor/fileannotationtab/FulltextSearchResultsTab.java
#	src/main/java/org/jabref/gui/externalfiles/ExternalFilesEntryLinker.java
#	src/main/java/org/jabref/gui/externalfiles/ImportHandler.java
#	src/main/java/org/jabref/gui/groups/GroupDialogView.java
#	src/main/java/org/jabref/gui/groups/GroupsPreferences.java
#	src/main/java/org/jabref/gui/maintable/MainTable.java
#	src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java
#	src/main/java/org/jabref/gui/maintable/columns/FileColumn.java
#	src/main/java/org/jabref/gui/preview/PreviewPanel.java
#	src/main/java/org/jabref/gui/search/GlobalSearchBar.java
#	src/main/java/org/jabref/gui/search/RebuildFulltextSearchIndexAction.java
#	src/main/java/org/jabref/gui/search/SearchResultsTableDataModel.java
#	src/main/java/org/jabref/logic/pdf/search/indexing/IndexingTaskManager.java
#	src/main/java/org/jabref/model/database/BibDatabaseContext.java
#	src/main/java/org/jabref/model/pdf/search/SearchFieldConstants.java
#	src/main/java/org/jabref/model/search/rules/SearchRules.java
#	src/main/java/org/jabref/preferences/JabRefPreferences.java
#	src/main/java/org/jabref/preferences/SearchPreferences.java
#	src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java
@JabRef JabRef deleted a comment from github-actions bot Sep 12, 2023
@calixtus
Copy link
Member

Should compile now, still heavy issues with the performance. Will have to investigate with jdk 21 and virtual threads.
But you can play around with this, test it and report issues here.

@github-actions
Copy link
Contributor

Your code currently does not meet JabRef's code guidelines. The tool reviewdog already placed comments on GitHub to indicate the places. See the tab "Files" in you PR. Please carefully follow the setup guide for the codestyle. Afterwards, please run checkstyle locally and fix the issues.

More information on code quality in JabRef is available at https://devdocs.jabref.org/getting-into-the-code/development-strategy.html.

@ThiloteE
Copy link
Member

Was not able to compile on Windows 10 with jdk 20.

C:\Prog\Development\JabRef_JabRef-JabRef\jabref>gradlew run
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reused, use --status for details

> Configure project :
Project : => 'org.jabref' Java module

> Task :compileJava
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:23: Fehler: Symbol nicht gefunden
class BstVMVisitor extends BstBaseVisitor<Integer> {
                           ^
  Symbol: Klasse BstBaseVisitor
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:40: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitStringsCommand(BstParser.StringsCommandContext ctx) {
                                                ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:52: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitIntegersCommand(BstParser.IntegersCommandContext ctx) {
                                                 ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:60: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitFunctionCommand(BstParser.FunctionCommandContext ctx) {
                                                 ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:67: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitMacroCommand(BstParser.MacroCommandContext ctx) {
                                              ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:75: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitReadCommand(BstParser.ReadCommandContext ctx) {
                                             ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:117: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitExecuteCommand(BstParser.ExecuteCommandContext ctx) {
                                                ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:125: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitIterateCommand(BstParser.IterateCommandContext ctx) {
                                                ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:135: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitReverseCommand(BstParser.ReverseCommandContext ctx) {
                                                ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:146: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitEntryCommand(BstParser.EntryCommandContext ctx) {
                                              ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:179: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitSortCommand(BstParser.SortCommandContext ctx) {
                                             ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:185: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitIdentifier(BstParser.IdentifierContext ctx) {
                                            ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:223: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitBstFunction(BstParser.BstFunctionContext ctx) {
                                             ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:235: Fehler: Package BstParser ist nicht vorhanden
    public Integer visitStackitem(BstParser.StackitemContext ctx) {
                                           ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstFunctions.java:517: Fehler: Symbol nicht gefunden
            visitor.visit(tree);
                   ^
  Symbol: Methode visit(ParseTree)
  Ort: Variable visitor von Typ BstVMVisitor
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstFunctions.java:884: Fehler: Symbol nicht gefunden
            visitor.visit((ParseTree) f1);
                   ^
  Symbol: Methode visit(ParseTree)
  Ort: Variable visitor von Typ BstVMVisitor
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstFunctions.java:894: Fehler: Symbol nicht gefunden
            visitor.visit((ParseTree) f2);
                   ^
  Symbol: Methode visit(ParseTree)
  Ort: Variable visitor von Typ BstVMVisitor
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:39: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:45: Fehler: Package BstParser ist nicht vorhanden
        for (BstParser.IdentifierContext identifierContext : ctx.ids.identifier()) {
                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:51: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:53: Fehler: Package BstParser ist nicht vorhanden
        for (BstParser.IdentifierContext identifierContext : ctx.ids.identifier()) {
                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:59: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:66: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:74: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:116: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:124: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:134: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:145: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:150: Fehler: Package BstParser ist nicht vorhanden
        BstParser.IdListOptContext entryFields = ctx.idListOpt(0);
                 ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:151: Fehler: Package BstParser ist nicht vorhanden
        for (BstParser.IdentifierContext identifierContext : entryFields.identifier()) {
                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:157: Fehler: Package BstParser ist nicht vorhanden
        BstParser.IdListOptContext entryIntegers = ctx.idListOpt(1);
                 ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:158: Fehler: Package BstParser ist nicht vorhanden
        for (BstParser.IdentifierContext identifierContext : entryIntegers.identifier()) {
                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:164: Fehler: Package BstParser ist nicht vorhanden
        BstParser.IdListOptContext entryStrings = ctx.idListOpt(2);
                 ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:165: Fehler: Package BstParser ist nicht vorhanden
        for (BstParser.IdentifierContext identifierContext : entryStrings.identifier()) {
                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:178: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:184: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:222: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:234: Fehler: Methode ├╝berschreibt oder implementiert keine Methode aus einem Supertyp
    @Override
    ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:240: Fehler: Package BstParser ist nicht vorhanden
                        case BstParser.STRING -> {
                                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:244: Fehler: Package BstParser ist nicht vorhanden
                        case BstParser.INTEGER ->
                                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:246: Fehler: Package BstParser ist nicht vorhanden
                        case BstParser.QUOTED ->
                                      ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:249: Fehler: Package BstParser ist nicht vorhanden
                } else if (childNode instanceof BstParser.StackContext) {
                                                         ^
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVMVisitor.java:252: Fehler: Symbol nicht gefunden
                    this.visit(childNode);
                        ^
  Symbol: Methode visit(ParseTree)
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVM.java:52: Fehler: Symbol nicht gefunden
        BstLexer lexer = new BstLexer(query);
        ^
  Symbol: Klasse BstLexer
  Ort: Klasse BstVM
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVM.java:52: Fehler: Symbol nicht gefunden
        BstLexer lexer = new BstLexer(query);
                             ^
  Symbol: Klasse BstLexer
  Ort: Klasse BstVM
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVM.java:55: Fehler: Symbol nicht gefunden
        BstParser parser = new BstParser(new CommonTokenStream(lexer));
        ^
  Symbol: Klasse BstParser
  Ort: Klasse BstVM
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVM.java:55: Fehler: Symbol nicht gefunden
        BstParser parser = new BstParser(new CommonTokenStream(lexer));
                               ^
  Symbol: Klasse BstParser
  Ort: Klasse BstVM
C:\Prog\Development\JabRef_JabRef-JabRef\jabref\src\main\java\org\jabref\logic\bst\BstVM.java:85: Fehler: Symbol nicht gefunden
        bstVMVisitor.visit(tree);
                    ^
  Symbol: Methode visit(ParseTree)
  Ort: Variable bstVMVisitor von Typ BstVMVisitor
Hinweis: Einige Eingabedateien verwenden oder ├╝berschreiben eine veraltete API.
Hinweis: Wiederholen Sie die Kompilierung mit -Xlint:deprecation, um Details zu erhalten.
Hinweis: Einige Eingabedateien verwenden nicht geprüfte oder unsichere Vorgänge.
Hinweis: Wiederholen Sie die Kompilierung mit -Xlint:unchecked, um Details zu erhalten.
48 Fehler

> Task :compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
> Run with --info option to get more log output.
> Run with --scan to get full insights.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.3/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD FAILED in 56s
6 actionable tasks: 3 executed, 3 up-to-date

@ThiloteE
Copy link
Member

Used the build from the website and found:

  • It is NOT possible to have the entry with the highest score on top when regex search is enabled.
  • It is almost impossible to discern if search filters are enabled or disabled with dark theme. (white symbol when disabled, and also white when enabled).
    image

@calixtus
Copy link
Member

gradlew clean?

@ThiloteE
Copy link
Member

Gradlew clean fixed the compilation, but now I get the following errors whenever I try to open a library:

java.lang.NullPointerException: Cannot invoke "org.jabref.gui.maintable.columns.MainTableColumn.getModel()" because "column" is null
	at org.jabref@100.0.0/org.jabref.gui.maintable.MainTable.lambda$new$7(MainTable.java:198)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.AbstractList$RandomAccessSpliterator.tryAdvance(AbstractList.java:708)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
	at org.jabref@100.0.0/org.jabref.gui.maintable.MainTable.lambda$new$10(MainTable.java:200)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at org.jabref@100.0.0/org.jabref.gui.maintable.MainTable.<init>(MainTable.java:195)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.createMainTable(LibraryTab.java:516)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.setupMainPanel(LibraryTab.java:535)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.<init>(LibraryTab.java:155)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.createLibraryTab(LibraryTab.java:849)
	at org.jabref@100.0.0/org.jabref.gui.importer.actions.OpenDatabaseAction.openTheFile(OpenDatabaseAction.java:195)
	at org.jabref@100.0.0/org.jabref.gui.importer.actions.OpenDatabaseAction.lambda$openFiles$0(OpenDatabaseAction.java:172)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.jabref@100.0.0/org.jabref.gui.importer.actions.OpenDatabaseAction.openFiles(OpenDatabaseAction.java:170)
	at org.jabref@100.0.0/org.jabref.gui.JabRefGUI.openLastEditedDatabases(JabRefGUI.java:332)
	at org.jabref@100.0.0/org.jabref.gui.JabRefGUI.openDatabases(JabRefGUI.java:185)
	at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
	at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
	at javafx.graphics@20/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
	at javafx.graphics@20/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics@20/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
	at java.base/java.lang.Thread.run(Thread.java:1623)

and


java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TableColumn.setTableView(javafx.scene.control.TableView)" because "<local7>" is null
	at javafx.controls@20/javafx.scene.control.TableView$4.onChanged(TableView.java:792)
	at javafx.base@20/javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
	at javafx.base@20/com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:162)
	at javafx.base@20/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:71)
	at javafx.base@20/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:238)
	at javafx.base@20/javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
	at javafx.base@20/javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
	at javafx.base@20/javafx.collections.ObservableListBase.endChange(ObservableListBase.java:210)
	at javafx.base@20/javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:109)
	at org.jabref@100.0.0/org.jabref.gui.maintable.MainTable.<init>(MainTable.java:124)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.createMainTable(LibraryTab.java:516)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.setupMainPanel(LibraryTab.java:535)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.<init>(LibraryTab.java:155)
	at org.jabref@100.0.0/org.jabref.gui.LibraryTab.createLibraryTab(LibraryTab.java:849)
	at org.jabref@100.0.0/org.jabref.gui.importer.actions.OpenDatabaseAction.openTheFile(OpenDatabaseAction.java:195)
	at org.jabref@100.0.0/org.jabref.gui.importer.actions.OpenDatabaseAction.lambda$openFiles$0(OpenDatabaseAction.java:172)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.jabref@100.0.0/org.jabref.gui.importer.actions.OpenDatabaseAction.openFiles(OpenDatabaseAction.java:170)
	at org.jabref@100.0.0/org.jabref.gui.JabRefGUI.openLastEditedDatabases(JabRefGUI.java:332)
	at org.jabref@100.0.0/org.jabref.gui.JabRefGUI.openDatabases(JabRefGUI.java:185)
	at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
	at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
	at javafx.graphics@20/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
	at javafx.graphics@20/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics@20/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
	at java.base/java.lang.Thread.run(Thread.java:1623)

@calixtus
Copy link
Member

hm, interesting, can reproduce the bug on my windows machine, but not on my arch linux laptop

# Conflicts:
#	CHANGELOG.md
#	src/main/java/org/jabref/model/search/rules/ContainsBasedSearchRule.java
#	src/main/java/org/jabref/model/search/rules/GrammarBasedSearchRule.java
#	src/main/java/org/jabref/model/search/rules/RegexBasedSearchRule.java
# Conflicts:
#	CHANGELOG.md
#	src/main/java/org/jabref/model/search/rules/ContainsBasedSearchRule.java
#	src/main/java/org/jabref/model/search/rules/GrammarBasedSearchRule.java
#	src/main/java/org/jabref/model/search/rules/RegexBasedSearchRule.java
@github-actions
Copy link
Contributor

The build of this PR is available at https://builds.jabref.org/pull/8963/merge.

@koppor
Copy link
Member

koppor commented Oct 17, 2023

@AEgit
Copy link

AEgit commented Oct 17, 2023

I will just mention this my old comment here as well, so that it is not forgotten: #4237 (comment)

I have noted that for the Lucene search approach (#8963 (comment)), the following solution has been suggested to the 'floating mode' problem:

Use gray background for score==0. See https://github.com/JabRef/jabref/issues/4237#issuecomment-993325334.

I am not familiar with the technicalities of Lucene, but I reckon a score of 0 represents an item, that does not match the search criteria at all. That is not (!) the same as what the old floating mode in JabRef 3.8.2 offered - the items in gray did match the search criteria to a certain degree. The only difference between the items with white background and those with gray background was, that the white ones belonged to the group, that the user had selected at the moment. The gray ones did not (!) belong to the selected group.

Hopefully, this old behaviour of JabRef can be restored with the new Lucene search.

@koppor
Copy link
Member

koppor commented Nov 15, 2023

Some notes on the search syntax. Users might find it confusing if partial-word-search is not the default search. See laurent22/joplin#6349 and laurent22/joplin#6455 for discussions in a related project.

Full search documentation of Joplin: https://joplinapp.org/help/apps/search

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Migrate JabRef search to Lucene
7 participants