在Lucene.NET索引中存储关系数据

fyj*_*ham 6 c# search lucene.net

我目前正在尝试在大型数据库上实现基于Lucene.NET的搜索,并且我试图搜索基本上是关系数据的问题.

在高级别,我正在尝试搜索的数据被分组,每个项目属于1到3个组.然后,我需要能够搜索组合组中的所有项目(EG:每个项目同时属于组A和组B).

这些分组中的每一个都有我正在搜索的数据中存在的ID和描述,但描述可能是彼此的子字符串(EG:一个名为"Stuff"的组和另一个"其他东西"),我不知道我想匹配具有我正在寻找的子字符串的类别.

我一直在考虑在不进行过滤的情况下将数据拉回来然后过滤ID,但出于性能原因,我打算对从Lucene返回的数据进行分页.我还考虑过将ID放在空格上并在场上进行文本搜索,但这似乎完全是黑客攻击......

有谁知道如何在Lucene.NET中最好地处理这种搜索?(只是在有人说我使用错误的工具之前澄清一下,这只是一组较大的过滤器的一部分,包括全文搜索.如果你仍然认为我使用了错误的工具,虽然我喜欢听听正确的是什么)

Hak*_*onB 5

我在存储关系数据方面遇到了一些问题我Lucene但是你应该很容易解决这个问题.

我猜你会对组字段进行标记,这样就可以在字段值中搜索子字符串.只需添加未加标记的字段,它应该像预期的那样工作.

请检查以下一小段代码:

internal class Program {
    private static void Main(string[] args) {
        var directory = new RAMDirectory();
        var writer = new IndexWriter(directory, new StandardAnalyzer());
        AddDocument(writer, "group", "stuff", Field.Index.UN_TOKENIZED);
        AddDocument(writer, "group", "other stuff", Field.Index.UN_TOKENIZED);
        writer.Close(true);

        var searcher = new IndexSearcher(directory);
        Hits hits = searcher.Search(new TermQuery(new Term("group", "stuff")));

        for (int i = 0; i < hits.Length(); i++) {
            Console.WriteLine(hits.Doc(i).GetField("group").StringValue());
        }
    }

    private static void AddDocument(IndexWriter writer, string name, string value, Field.Index index) {
        var document = new Document();
        document.Add(new Field(name, value, Field.Store.YES, index));
        writer.AddDocument(document);
    }
}
Run Code Online (Sandbox Code Playgroud)

该示例将两个文档添加到索引中,这些文档未被标记,搜索内容并获得一个匹配.如果您更改了代码以将其添加为令牌化,那么您现在可以看到两次点击.

将Lucene用于关系数据的问题在于,可能期望通配符和范围搜索始终有效.如果由于Lucene解析这些查询的方式索引很大,情况并非如此.

另一个说明行为的示例:

    private static void Main(string[] args) {
        var directory = new RAMDirectory();
        var writer = new IndexWriter(directory, new StandardAnalyzer());

        var documentA = new Document();
        documentA.Add(new Field("name", "A", Field.Store.YES, Field.Index.UN_TOKENIZED));
        documentA.Add(new Field("group", "stuff", Field.Store.YES, Field.Index.UN_TOKENIZED));
        documentA.Add(new Field("group", "other stuff", Field.Store.YES, Field.Index.UN_TOKENIZED));
        writer.AddDocument(documentA);
        var documentB = new Document();
        documentB.Add(new Field("name", "B", Field.Store.YES, Field.Index.UN_TOKENIZED));
        documentB.Add(new Field("group", "stuff", Field.Store.YES, Field.Index.UN_TOKENIZED));
        writer.AddDocument(documentB);
        var documentC = new Document();
        documentC.Add(new Field("name", "C", Field.Store.YES, Field.Index.UN_TOKENIZED));
        documentC.Add(new Field("group", "other stuff", Field.Store.YES, Field.Index.UN_TOKENIZED));
        writer.AddDocument(documentC);

        writer.Close(true);

        var query1 = new TermQuery(new Term("group", "stuff"));
        SearchAndDisplay("First sample", directory, query1);

        var query2 = new TermQuery(new Term("group", "other stuff"));
        SearchAndDisplay("Second sample", directory, query2);

        var query3 = new BooleanQuery();
        query3.Add(new TermQuery(new Term("group", "stuff")), BooleanClause.Occur.MUST);
        query3.Add(new TermQuery(new Term("group", "other stuff")), BooleanClause.Occur.MUST);
        SearchAndDisplay("Third sample", directory, query3);
    }

    private static void SearchAndDisplay(string title, Directory directory, Query query3) {
        var searcher = new IndexSearcher(directory);
        Hits hits = searcher.Search(query3);
        Console.WriteLine(title);
        for (int i = 0; i < hits.Length(); i++) {
            Console.WriteLine(hits.Doc(i).GetField("name").StringValue());
        }
    }
Run Code Online (Sandbox Code Playgroud)