2010-03-19 10 views
1

Je veux trier mes résultats de recherche lucene (.net) par un champ de date (date1), mais si la date1 n'est pas définie, j'aimerais utiliser date2. La méthode de tri traditionnelle consiste à trier par date1, puis à trier les valeurs identiques par date 2. Cela signifierait que chaque fois que je reviendrais à date2, ces valeurs seraient en haut (ou en bas) de l'ensemble de résultats. Je voudrais entrelacer les valeurs date2 avec les valeurs date1. En d'autres termes, je veux trier (date1! = Null? Date1: date2).Comment faire pour trier par un champ qui a une valeur alternative si null dans lucene?

Est-ce possible en lucene? Je pense que je pourrais le faire dans la phase de création d'index (il suffit de mettre la valeur de date pertinente dans un nouveau champ) mais je n'ai pas assez de contrôle sur le processus d'indexation pour pouvoir le faire, je voudrais un solution de tri.

Des idées?

Merci Matt

+0

Ugh, je déteste Lucene questions spécifiques à une plate-forme spécifique comme. Net .. J'ai eu la même question, mais dans une autre plate-forme, souhaite que les solutions étaient plate-forme indépendante :( –

Répondre

2

Il s'avère que c'est très facile. Vous devez implémenter ScoreDocComparator, comme Yuval l'a suggéré. Cependant, vous n'avez besoin de l'implémenter qu'une seule fois (j'ai un document avec deux dates, je ne veux pas trier par date1 puis date2, mais plutôt par date1 si elle est spécifiée, ou par date2 sinon.Pensez à une date réelle et un date provisoire, je veux utiliser la date réelle si elle est disponible, mais si ce n'est pas le cas, la date provisoire est suffisante).

Voici mon 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]]; 
    } 
} 

Mon ActualOrProvisionalDateSortComparatorSource passe FieldCache_Fields.DEFAULT et nous sommes loin!

1

J'ai une idée qui peut fonctionner:

  • utilisation Search(Query, Filter, Sort)
  • Afin de créer l'objet Trier, utilisez le constructeur Sort(SortField[])
  • Créer un SortField pour les deux champs de date. pour chacun d'entre eux utiliser un ScoreDocComparator pour gérer le cas des valeurs nulles. Dans ce cas, la fonction Compare() retournera zéro. Veuillez voir this blog post à propos de l'utilisation de tri personnalisé dans Java Lucene. Je crois que ce n'est pas difficile à traduire en Lucene.net.