Sorting with custom SortComparator

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Sorting with custom SortComparator

Theodan
Hello.

I am trying to sort my query results on a String field called "AssetType" and then on the relevancy score, but I need a particular ordering of the possible values in "AssetType" (i.e. first "Video", then "Article", etc.).

I have tried doing this with a custom SortComparator that returns Integers from getComparable(), as follows:

===========================

public class LuceneIndexSearchCommand extends AbstractSearchCommand {
       
        protected boolean execute(SearchContext context) throws Exception {
               
                ...
               
                Hits hits = new Hits();
               
                ...

                BooleanQuery keywordQuery = new BooleanQuery();

                ...

                Query query = queryParser.parse(finalQuery);

                ConstantScoreRangeQuery constantScoreRangeQuery = new ConstantScoreRangeQuery("assettype", null, null, true, true);

                BooleanQuery booleanQuery = new BooleanQuery();
                booleanQuery.add(query, Occur.MUST);
                booleanQuery.add(constantScoreRangeQuery, Occur.MUST);

                SortField[] sortFields = new SortField[] {
                                new SortField("assettype", new AssetTypeSortComparator()),
                                SortField.FIELD_SCORE
                };
                hits.recordHits(searcher.search(booleanQuery, new Sort(sortFields)));
               
                ...
       
        }

        private static class AssetTypeSortComparator extends SortComparator {
               
                private static final Map ASSET_TYPE_ORDER_MAP = new HashMap();
                private static final Integer DEFAULT_ORDER = new Integer(3);
               
                static {
                        ASSET_TYPE_ORDER_MAP.put("Interactive".toLowerCase(), new Integer(0));
                        ASSET_TYPE_ORDER_MAP.put("Video".toLowerCase(), new Integer(0));
                        ASSET_TYPE_ORDER_MAP.put("EncyclopediaArticles".toLowerCase(), new Integer(1));
                        ASSET_TYPE_ORDER_MAP.put("Image".toLowerCase(), new Integer(2));
                }
               
                protected Comparable getComparable(String termtext) {
                        if (ASSET_TYPE_ORDER_MAP.containsKey(termtext.toLowerCase())) {
                                return (Integer)ASSET_TYPE_ORDER_MAP.get(termtext.toLowerCase());
                        }
                        else {
                                return DEFAULT_ORDER;
                        }
    }
               
    };
   
}

===========================

but my Hits don't come back sorted.  They seem to be in the same unsorted order as before I started trying to use the custom SortComparator.

I have debugged through SortComparator and FieldCacheImpl, and the "cachedValues" array does seem to correctly contain Integer items corresponding to most of my 80,000+ docs.  The rest of the items in the array are null, corresponding to those docs that are missing a value for the "AssetType" field.

Also, FYI, I am using ConstantScoreRangeQuery because the "AssetType" field is sometimes missing from certain of the docs, and if I don't use ConstantScoreRangeQuery then I get NullPointerException on SortComparator.java:37, as has been discussed before on this mailing list.

Any help would be greatly appreciated.

-Theo
Reply | Threaded
Open this post in threaded view
|

Re: Sorting with custom SortComparator

Theodan
Never mind.  The sorting was working correctly.  I was just misinterpretting the results I was seeing.

-Theo


Theodan wrote
Hello.

I am trying to sort my query results on a String field called "AssetType" and then on the relevancy score, but I need a particular ordering of the possible values in "AssetType" (i.e. first "Video", then "Article", etc.).

I have tried doing this with a custom SortComparator that returns Integers from getComparable(), as follows:

===========================

public class LuceneIndexSearchCommand extends AbstractSearchCommand {
       
        protected boolean execute(SearchContext context) throws Exception {
               
                ...
               
                Hits hits = new Hits();
               
                ...

                BooleanQuery keywordQuery = new BooleanQuery();

                ...

                Query query = queryParser.parse(finalQuery);

                ConstantScoreRangeQuery constantScoreRangeQuery = new ConstantScoreRangeQuery("assettype", null, null, true, true);

                BooleanQuery booleanQuery = new BooleanQuery();
                booleanQuery.add(query, Occur.MUST);
                booleanQuery.add(constantScoreRangeQuery, Occur.MUST);

                SortField[] sortFields = new SortField[] {
                                new SortField("assettype", new AssetTypeSortComparator()),
                                SortField.FIELD_SCORE
                };
                hits.recordHits(searcher.search(booleanQuery, new Sort(sortFields)));
               
                ...
       
        }

        private static class AssetTypeSortComparator extends SortComparator {
               
                private static final Map ASSET_TYPE_ORDER_MAP = new HashMap();
                private static final Integer DEFAULT_ORDER = new Integer(3);
               
                static {
                        ASSET_TYPE_ORDER_MAP.put("Interactive".toLowerCase(), new Integer(0));
                        ASSET_TYPE_ORDER_MAP.put("Video".toLowerCase(), new Integer(0));
                        ASSET_TYPE_ORDER_MAP.put("EncyclopediaArticles".toLowerCase(), new Integer(1));
                        ASSET_TYPE_ORDER_MAP.put("Image".toLowerCase(), new Integer(2));
                }
               
                protected Comparable getComparable(String termtext) {
                        if (ASSET_TYPE_ORDER_MAP.containsKey(termtext.toLowerCase())) {
                                return (Integer)ASSET_TYPE_ORDER_MAP.get(termtext.toLowerCase());
                        }
                        else {
                                return DEFAULT_ORDER;
                        }
    }
               
    };
   
}

===========================

but my Hits don't come back sorted.  They seem to be in the same unsorted order as before I started trying to use the custom SortComparator.

I have debugged through SortComparator and FieldCacheImpl, and the "cachedValues" array does seem to correctly contain Integer items corresponding to most of my 80,000+ docs.  The rest of the items in the array are null, corresponding to those docs that are missing a value for the "AssetType" field.

Also, FYI, I am using ConstantScoreRangeQuery because the "AssetType" field is sometimes missing from certain of the docs, and if I don't use ConstantScoreRangeQuery then I get NullPointerException on SortComparator.java:37, as has been discussed before on this mailing list.

Any help would be greatly appreciated.

-Theo