Как реализовать пользовательский фильтр с помощью Lucene.net?

Ниже приведен код из книги Lucene In Action (первоначально на Java). Он предназначен для создания списка разрешенных документов (с точки зрения разрешения пользователя) для фильтрации результатов поиска. Проблема заключается в том, что метод termsDocs.Read() не принимает массивы 'doc' и 'freq', которые передаются по ссылке, поэтому они все еще пусты, когда дело доходит до установки бит в битовом массиве.

Может ли кто-нибудь помочь, примеры использования пользовательских фильтров Lucene (особенно в .net) кажутся тонкими на земле. Спасибо.

public class LuceneCustomFilter : Lucene.Net.Search.Filter
{
    string[] _luceneIds;

    public LuceneCustomFilter(string[] luceneIds)
    {
        _luceneIds = luceneIds;
    }

    public override BitArray Bits(Lucene.Net.Index.IndexReader indexReader)
    {
        BitArray bitarray = new BitArray(indexReader.MaxDoc());

        int[] docs = new int[1];
        int[] freq = new int[1];

        for (int i = 0; i < _luceneIds.Length; i++)
        {
            if (!string.IsNullOrEmpty(_luceneIds[i]))
            {
                Lucene.Net.Index.TermDocs termDocs = indexReader.TermDocs(
                    new Lucene.Net.Index.Term(@"luceneId", _luceneIds[i]));

                int count = termDocs.Read(docs, freq);

                if (count == 1)
                {
                    bitarray.Set(docs[0], true);
                }
            }
        }

        return bitarray;
    }
}

Я использую Lucene.net 2.0.0.4, но интерфейс TermDocs по-прежнему остается таким же в последней ветки: https://svn.apache.org/repos/asf/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/TermDocs.cs

Ответ 1

Вот рабочий пример Lucene.NET с использованием настраиваемого фильтра, на который вы можете взглянуть:

using System;
using System.Collections;
using Lucene.Net.Analysis;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;

class Program
{
    static void Main(string[] args)
    {
        Directory index = new RAMDirectory();
        Analyzer analyzer = new KeywordAnalyzer();
        IndexWriter writer = new IndexWriter(index, analyzer, true);

        Document doc = new Document();
        doc.Add(new Field("title", "t1", Field.Store.YES, 
            Field.Index.TOKENIZED));
        writer.AddDocument(doc);
        doc = new Document();
        doc.Add(new Field("title", "t2", Field.Store.YES, 
            Field.Index.TOKENIZED));
        writer.AddDocument(doc);

        writer.Close();

        Searcher searcher = new IndexSearcher(index);
        Query query = new MatchAllDocsQuery();
        Filter filter = new LuceneCustomFilter();
        Sort sort = new Sort("title", true);
        Hits hits = searcher.Search(query, filter, sort);
        IEnumerator hitsEnumerator = hits.Iterator();

        while (hitsEnumerator.MoveNext())
        {
            Hit hit = (Hit)hitsEnumerator.Current;
            Console.WriteLine(hit.GetDocument().GetField("title").
                StringValue());
        }
    }
}

public class LuceneCustomFilter : Filter
{
    public override BitArray Bits(IndexReader indexReader)
    {
        BitArray bitarray = new BitArray(indexReader.MaxDoc());

        int[] docs = new int[1];
        int[] freq = new int[1];

        TermDocs termDocs = indexReader.TermDocs(
                new Term(@"title", "t1"));

        int count = termDocs.Read(docs, freq);
        if (count == 1)
        {
            bitarray.Set(docs[0], true);
        }
        return bitarray;
    }
}

Ответ 2

Немного путают здесь, потому что передача массива действительно передает его по ссылке. Например, следующая запись будет печатать 10 10 10 10 10, показывая, что значения массива были обновлены.

Я что-то пропустил?

    public void TestPassing()
    {
        int[] stuff = new int[] {5, 5, 5, 5};

        Add(stuff, 5);
        for (int i = 0; i < stuff.Length; i++)
        {
            Console.Write(stuff[i]);
        }
    }

    public void Add(int[] stuff, int x)
    {
        for(int i = 0; i < stuff.Length; i++)
        {
            stuff[i] = stuff[i] + x;
        }
    }