开发者

How to sort by a field that has an alternative value if null in lucene?

I want to sort my lucene(.net) search results by a date field (date1), but if date1 is not set, I'd like to use date2.

The traditional sort method is to sort by date1, and then sort the values that are the same by date 2. This would mean that whenever I did fall back to date2, these values would be at the top (or bottom) of the result set. I'd like to interleave the date2 values with the date1 values.

In other words, I want to sort on (date1开发者_JS百科 != null ? date1 : date2).

Is this possible in lucene?

I reckon I could do this in the index creation phase (just put the relevant date value in a new field) but I don't have enough control of the indexing process to be able to do this, so would like a sorting solution.

Any ideas?

Thanks Matt


Turns out it's very easy. You do have to implement ScoreDocComparator, as Yuval suggested. However, you only need to implement it once (I have a document with two dates, I don't want to sort by date1 then date2, but rather by date1 if it's specified, or date2 if not. Think of an actual date and a provisional date. I want to use the actual date if it's available, but if not, then the provisional date is good enough).

Here's my code:

public class ActualOrProvisionalDateSortComparator : ScoreDocComparator
{
    private readonly StringIndex actualDates;
    private readonly StringIndex provisionalDates;

    public TxOrCreatedDateSortComparator(IndexReader reader, FieldCache fieldCache)
    {
        actualDates = fieldCache.GetStringIndex(reader, "actualDate");
        provisionalDates = fieldCache.GetStringIndex(reader, "provisionalDate");
    }

    public int Compare(ScoreDoc i, ScoreDoc j)
    {
        var date1 = GetValue(i.doc);
        var date2 = GetValue(j.doc);

        return date1.CompareTo(date2);
    }

    public IComparable SortValue(ScoreDoc i)
    {
        return GetValue(i.doc);
    }

    public int SortType()
    {
        return SortField.CUSTOM;
    }

    private string GetValue(int doc)
    {
        return actualDates.Lookup[actualDates.Order[doc]] ?? provisionalDates.Lookup[provisionalDates.Order[doc]];
    }
}

My ActualOrProvisionalDateSortComparatorSource passes in FieldCache_Fields.DEFAULT and we're away!


I have an idea that may work:

  • use Search(Query, Filter, Sort)
  • In order to create the Sort object, use the Sort(SortField[]) constructor
  • Create a SortField for both date fields. for each of them use a ScoreDocComparator to handle the case of null values. In this case the Compare() function will return zero. Please see this blog post about using custom sort in Java Lucene. I believe it is not hard to translate this into Lucene.net.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜