Pregunta

Actualmente me gusta esto:

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

Como puede ver, primero colecciono TODOS los campos (varios miles) y luego los distingo, posiblemente omito algunos y elimino algunos.

Siento que debería haber una mejor manera de hacer esto.

¿Fue útil?

Solución

Honestamente, no estoy seguro de que lo haya, ya que Lucene no proporciona una funcionalidad 'distinta'. Creo que con SOLR puedes usar una búsqueda de facetas para lograr esto, pero si quieres esto en Lucene, deberías escribir algún tipo de funcionalidad de facetas tú mismo. Por lo tanto, siempre que no tenga problemas de rendimiento, debería estar bien de esta manera.

Otros consejos

Vinculando esta pregunta a una pregunta anterior tuya (re: " Demasiadas cláusulas "), creo que definitivamente deberías consultar la enumeración de términos del lector de índice. Almacene en caché los resultados (utilicé un diccionario ordenado con clave en el nombre del campo, con una lista de términos como los datos, hasta un máximo de 100 términos por campo) hasta que el lector de índice se vuelva no válido y listo.

O tal vez debería decir que cuando me enfrenté a un problema similar al tuyo, eso es lo que hice.

Espero que esto ayude,

Le sugiero que busque una lógica para omitir este tipo de iteración, pero si no hay una solución en su contexto, puede obtener una ganancia de rendimiento con el siguiente código
1) En el momento del índice, es mejor colocar el campo que desea iterar, en el primer campo

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

2) entonces necesitas definir un FieldSelector como este

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

3) Luego, cuando quieras iterar y seleccionar este campo, debes hacer algo como esto

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

El rendimiento del código anterior es mucho mejor que el código que proporcionó porque omite la lectura de campos de documentos innecesarios y ahorra tiempo.

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;
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top