0

I am trying to search through a mongo database to find a user given search term in one of the fields:

    @GetMapping(value = {"/classes/search/{term}"})
    public String className (
        @PathVariable(required = true, value = "term") String term
    ) throws Exception {
        // Escape user input
        final String filteredTerm = escapeUserInput(term);

        // Match using Bson filter
        ArrayList<Document> matchedClasses = new ArrayList<Document>();
        for (String modName : DATABASE.listCollectionNames()) {
            ArrayList<Document> filteredContents = new ArrayList<Document>();
            try {
                getCollection(modName).find(
                    Filters.or(
                        Filters.text(filteredTerm),
                        Filters.eq("count", Long.parseLong(filteredTerm))
                    )
                ).into(filteredContents);
            } catch (NumberFormatException e) {
                getCollection(modName).find(Filters.text(filteredTerm)).into(filteredContents);
            }

            // Add to final doc if match is found
            if (filteredContents != null) {
                matchedClasses.addAll(filteredContents);
            }
        }

        return String.valueOf(matchedClasses
            .stream()
            .distinct()
            .sorted()
            .collect(Collectors.toList())
        );

    }

}

All getCollection() does is retrieve the mongo collection.

When passing any search term that SUCCESSFULLY matches something in the database, I get a ClassCastException supposedly on Line 140 (.collect(Collectors.toList()))

java.lang.ClassCastException: class org.bson.Document cannot be cast to class java.lang.Comparable (org.bson.Document is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
    at java.base/java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47) ~[na:na]
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:na]
    at java.base/java.util.TimSort.sort(TimSort.java:220) ~[na:na]
    at java.base/java.util.Arrays.sort(Arrays.java:1515) ~[na:na]
    at java.base/java.util.ArrayList.sort(ArrayList.java:1750) ~[na:na]
    at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392) ~[na:na]
    at java.base/java.util.stream.DistinctOps$1$2.end(DistinctOps.java:168) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
    at com.api.main.Executer.className(Executer.java:140) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
<TRUNCATED>

I suspect it's something to do with Filters.text as that is what I changed which has started to cause this error but I don't understand why and where my next step from here would be?

2
  • You are calling sorted on the stream of Document. If it doesn't implement Comparable, you should provide a custom comparator as the argument of sorted. Commented Jun 24, 2021 at 19:02
  • String.valueOf(matchedClasses… , you are trying to convert a list of objects to a string. I assume this isn’t supported and it begs the question, why? Commented Jun 24, 2021 at 19:07

1 Answer 1

3

matchedClasses is an ArrayList<Document> and Document does not implement Comparable.

When running .collect(Collectors.toList()), it also tries to sort the Stream elements because you called sorted. Bot for sorting, the elements need to either implement Comparable or pass a Comparator to .sorted().

As Document is a MongoDB class that you cannot control, you need to pass a Compatator to .sorted():

//...
.sorted((document1,document2)->/*compare documents here*/)
//...
Sign up to request clarification or add additional context in comments.

3 Comments

That is confusing as I have a similar function above that collects a ArrayList<Document> and returns successfully
java ArrayList<Document> dbContents = new ArrayList<Document>(); <TRUNCATED> return String.valueOf(dbContents .stream() .distinct() .map(typeDoc -> typeDoc.toJson()) .sorted() .collect(Collectors.toList()) );
Ah I see what I've done, I've been a silly goose. I forgot to convert the Document objects to JSON strings like I had done with my other route using .map(typeDoc -> typeDoc.toJson()) prior to using sorted(). Now resolved and will accept this answer as it basically implies the same logic. Thanks for all the help :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.