在Hibernate Search中搜索首选项

时间:2014-01-03 11:48:46

标签: java hibernate sorting lucene hibernate-search

我正在使用Hibernate Search 3.6.2,我想在前面对特定文档进行排序。出于这个原因,我已经编写了一个自定义比较器-Inource,但不知何故它似乎不起作用。

我希望将包含这些首选值的文档排序到前面。

这是我到目前为止所做的:

public class PreferenceFieldComparatorSource<T> extends FieldComparatorSource {

    private static final long serialVersionUID = -8959374194451783596L;

    private final List<?> preferred;
    private final Class<?> clazz;
    private final StringBridge stringBridge;

    @SafeVarargs
    public PreferenceFieldComparatorSource(Class<T> clazz,
            StringBridge stringBridge, T... preferred) {
        this(clazz, stringBridge, Arrays.asList(preferred));
    }

    public PreferenceFieldComparatorSource(Class<T> clazz,
            StringBridge stringBridge, List<T> preferred) {
        this.clazz = clazz;
        this.stringBridge = stringBridge;
        this.preferred = preferred;
    }

    @Override
    public FieldComparator<String> newComparator(final String fieldName,
            int numHits, int sortPos, final boolean reversed)
            throws IOException {
        return new FieldComparator<String>() {

            private String[] values;
            private String bottom;
            private String[] currentReaderValues;

            @Override
            public int compare(int slot1, int slot2) {
                return this.compare(this.values[slot1], this.values[slot2]);
            }

            @Override
            public int compareBottom(int doc) throws IOException {
                return this.compare(this.bottom, this.currentReaderValues[doc]);
            }

            @Override
            public void copy(int slot, int doc) throws IOException {
                this.values[slot] = this.currentReaderValues[doc];
            }

            @Override
            public void setBottom(int slot) {
                this.bottom = this.values[slot];
            }

            @Override
            public void setNextReader(IndexReader reader, int docBase)
                    throws IOException {
                System.out.println("fieldName: " + fieldName);

                this.currentReaderValues = new String[reader.maxDoc()];
                this.values = new String[reader.maxDoc()];
                for (int i = 0; i < currentReaderValues.length; ++i) {
                    try {
                        this.currentReaderValues[i] = reader.document(docBase)
                                .get(fieldName);
                    } catch (ClassCastException e) {
                        throw new IllegalArgumentException(
                                PreferenceFieldComparatorSource.this.stringBridge
                                        + " doesn't convert strings into "
                                        + PreferenceFieldComparatorSource.this.clazz);
                    }
                }
            }

            @Override
            public String value(int slot) {
                return this.values[slot];
            }

            private int compare(Object first, Object second) {
                // if none of the given values is in the preferred lists
                // the index is -1 but the compare function will still work
                // correctly
                // and will only move the preferred ones.
                int firstIndex = PreferenceFieldComparatorSource.this.preferred
                        .indexOf(PreferenceFieldComparatorSource.this.stringBridge
                                .objectToString(first));
                int secondIndex = PreferenceFieldComparatorSource.this.preferred
                        .indexOf(PreferenceFieldComparatorSource.this.stringBridge
                                .objectToString(second));
                int result = Integer.compare(firstIndex, secondIndex);
                if (reversed) {
                    result *= -1;
                }
                return result;
            }

        };
    }

}

似乎没有调用compare方法。对于这种情况,我在这堂课中做错了什么?

编辑:

澄清评论中的陈述:

         @Override
         protected boolean lessThan(final Entry hitA, final Entry hitB) {

             assert hitA != hitB;
             assert hitA.slot != hitB.slot;

             int numComparators = comparators.length;
             for (int i = 0; i < numComparators; ++i) {
                 final int c = reverseMul[i] * comparators[i].compare(hitA.slot,
             hitB.slot);
             if (c != 0) {
             // Short circuit
             return c > 0;
             }
         }

         // avoid random sort order that could lead to duplicates (bug
         #31241):
         return hitA.doc > hitB.doc;
        }

1 个答案:

答案 0 :(得分:0)

我明白了。要么我误读了Sort类的文档,要么它错了。它清楚地表明它是连续排序的,但它并不像连续3次排序java列表那样。相反,它的行为更像是反向。

来自Hibernate-Search源代码:

     @Override
     protected boolean lessThan(final Entry hitA, final Entry hitB) {

         assert hitA != hitB;
         assert hitA.slot != hitB.slot;

         int numComparators = comparators.length;
         for (int i = 0; i < numComparators; ++i) {
             final int c = reverseMul[i] * comparators[i].compare(hitA.slot,
         hitB.slot);
         if (c != 0) {
         // Short circuit
         return c > 0;
         }
     }

     // avoid random sort order that could lead to duplicates (bug
     #31241):
     return hitA.doc > hitB.doc;
    }

而且我的比较器错了:

public class PreferenceFieldComparatorSource<T> extends FieldComparatorSource {

    private static final long serialVersionUID = -8959374194451783596L;

    private final List<?> preferred;
    private final Class<?> clazz;
    private final TwoWayStringBridge stringBridge;

    @SafeVarargs
    public PreferenceFieldComparatorSource(Class<T> clazz,
            TwoWayStringBridge stringBridge, T... preferred) {
        this(clazz, stringBridge, Arrays.asList(preferred));
    }

    public PreferenceFieldComparatorSource(Class<T> clazz,
            TwoWayStringBridge stringBridge, List<T> preferred) {
        this.clazz = clazz;
        this.stringBridge = stringBridge;
        this.preferred = preferred;
    }

    @Override
    public FieldComparator<String> newComparator(final String fieldName,
            int numHits, int sortPos, final boolean reversed)
            throws IOException {
        return new FieldComparator<String>() {

            private String[] values;
            private String bottom;
            private String[] currentReaderValues;

            @Override
            public int compare(int slot1, int slot2) {
                return this.compare(this.values[slot1], this.values[slot2]);
            }

            @Override
            public int compareBottom(int doc) throws IOException {
                return this.compare(this.bottom, this.currentReaderValues[doc]);
            }

            @Override
            public void copy(int slot, int doc) throws IOException {
                this.values[slot] = this.currentReaderValues[doc];
            }

            @Override
            public void setBottom(int slot) {
                this.bottom = this.values[slot];
            }

            @Override
            public void setNextReader(IndexReader reader, int docBase)
                    throws IOException {                
                this.currentReaderValues = new String[reader.maxDoc()];
                this.values = new String[reader.maxDoc()];
                for (int i = 0; i < currentReaderValues.length; ++i) {
                    try {
                        this.currentReaderValues[i] = reader.document(i)
                                .get(fieldName);
                    } catch (ClassCastException e) {
                        throw new IllegalArgumentException(
                                PreferenceFieldComparatorSource.this.stringBridge
                                        + " doesn't convert strings into "
                                        + PreferenceFieldComparatorSource.this.clazz);
                    }
                }
            }

            @Override
            public String value(int slot) {
                return this.values[slot];
            }

            private int compare(Object first, Object second) {
                int firstIndex = PreferenceFieldComparatorSource.this.preferred
                        .indexOf(PreferenceFieldComparatorSource.this.stringBridge
                                .stringToObject((String) first));
                int secondIndex = PreferenceFieldComparatorSource.this.preferred
                        .indexOf(PreferenceFieldComparatorSource.this.stringBridge
                                .stringToObject((String) second));
                int result;
                if(firstIndex == -1 || secondIndex == -1) {
                    if(firstIndex == secondIndex) {
                        result = 0;
                    } else if(firstIndex == -1) {
                        result = 1;
                    } else {
                        result = -1;
                    }
                } else {
                    result = Integer.compare(firstIndex, secondIndex);
                }
                if (reversed) {
                    result *= -1;
                }
                return result;
            }

        };
    }

}