Question

Actuellement, j'aime bien ceci:

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();

Comme vous pouvez le constater, je commence par collecter TOUS les champs (plusieurs milliers), puis à les distinguer, éventuellement à en sauter quelques-uns et à les supprimer.

Je pense qu'il devrait exister un meilleur moyen de le faire.

Était-ce utile?

La solution

Honnêtement, je ne suis pas sûr que oui, car Lucene ne fournit pas de fonctionnalités «distinctes». Je crois qu'avec SOLR, vous pouvez utiliser une recherche de facettes pour y parvenir, mais si vous le souhaitez dans Lucene, vous devez écrire vous-même une fonctionnalité de facette. Donc, tant que vous ne rencontrez aucun problème de performances, vous devriez être ok de cette façon.

Autres conseils

Liant cette question à une de vos précédentes questions (concernant: "Trop de clauses"), je pense que vous devriez absolument regarder l'énumération des termes du lecteur d'index. Cachez les résultats (j'ai utilisé un dictionnaire trié indexé sur le nom du champ, avec une liste de termes en tant que données, avec un maximum de 100 termes par champ) jusqu'à ce que le lecteur d'index devienne invalide et que vous partiez.

Ou peut-être devrais-je dire que, face à un problème similaire au vôtre, c'est ce que j'ai fait.

J'espère que cela vous aidera,

Je vous suggère de trouver une logique pour ignorer ce type d'itération, mais s'il n'y a pas de solution dans votre contexte, vous pouvez obtenir un gain de performance avec le code suivant.
1) au moment de l'indexation, il est préférable de mettre le champ que vous souhaitez itérer, dans le premier champ

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

2) alors vous devez définir un FieldSelector comme ceci

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

3) Ensuite, lorsque vous souhaitez effectuer une itération et sélectionner ce champ, vous devez faire quelque chose comme ceci

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

Les performances du code ci-dessus sont bien meilleures que le code que vous avez fourni, car elles empêchent la lecture des champs de document inutiles et font gagner du temps.

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;
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top