Domanda

Attualmente mi piace questo:

IndexSearcher searcher = new IndexSearcher(lucenePath);
Hits hits = searcher.Search(query);
Document doc;
List<string> companyNames = new List<string>();

for (int i = 0; i < hits.Length(); i++)
{
    doc = hits.Doc(i);
    companyNames.Add(doc.Get("companyName"));
}
searcher.Close();

companyNames = companyNames.Distinct<string>().Skip(offSet ?? 0).ToList();
return companyNames.Take(count??companyNames.Count()).ToList();

Come puoi vedere, per prima cosa raccolgo TUTTI i campi (diverse migliaia) e poi li distinguo, possibilmente saltandone alcuni ed eliminandone alcuni.

Sento che dovrebbe esserci un modo migliore per farlo.

È stato utile?

Soluzione

Non sono sicuro che esista, in quanto Lucene non fornisce funzionalità "distinte". Credo che con SOLR sia possibile utilizzare una ricerca di sfaccettature per raggiungere questo obiettivo, ma se lo si desidera in Lucene, è necessario scrivere una sorta di funzionalità di sfaccettatura da soli. Quindi, purché non si verifichino problemi di prestazioni, dovresti andare bene in questo modo.

Altri suggerimenti

Legando questa domanda a una tua domanda precedente (ri: "Troppe clausole"), penso che dovresti assolutamente guardare il termine enumerazione dal lettore di indici. Memorizza nella cache i risultati (ho usato un dizionario ordinato digitato sul nome del campo, con un elenco di termini come dati, fino a un massimo di 100 termini per campo) fino a quando il lettore di indici diventa invalido e vai via.

O forse dovrei dire che di fronte a un problema simile al tuo è quello che ho fatto.

Spero che questo aiuti,

Ti suggerisco di trovare una logica per saltare questo tipo di iterazione ma se non esiste una soluzione nel tuo contesto, puoi ottenere un miglioramento delle prestazioni con il seguente codice
1) al momento dell'indice è meglio mettere il campo che si desidera iterare, nel primo campo

Document doc = new Document();
Field companyField = new Field(...);
doc.Add(companyField);
...

2) quindi devi definire un FieldSelector come questo

class CompanyNameFieldSelector : FieldSelector
{
    public FieldSelectorResult Accept(string fieldName)
    {
        return (fieldName == "companyName" ? FieldSelectorResult.LOAD_AND_BREAK : FieldSelectorResult.NO_LOAD);
    }
}

3) Quindi quando vuoi iterare e scegliere questo campo dovresti fare qualcosa del genere

FieldSelector companySelector = new CompanyNameFieldSelector();
// when you iterate through your index
doc = hits.Doc(i);
doc.Get("companyName", companySelector);

Le prestazioni del codice sopra riportato sono molto migliori del codice fornito perché salta la lettura di campi di documenti non necessari e consente di risparmiare tempo.

public List<string> GetDistinctTermList(string fieldName)
    {
        List<string> list = new List<string>();

        using (IndexReader reader = idxWriter.GetReader())
        {
            TermEnum te = reader.Terms(new Term(fieldName));

            if (te != null && te.Term != null && te.Term.Field == fieldName)
            {
                list.Add(te.Term.Text);

                while (te.Next())
                {
                    if (te.Term.Field != fieldName)
                        break;
                    list.Add(te.Term.Text);
                }
            }
        }

        return list;
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top