【问题标题】:Storing relational data in a Lucene.NET index在 Lucene.NET 索引中存储关系数据
【发布时间】:2010-12-18 03:35:45
【问题描述】:

我目前正在尝试在大型数据库上实现基于 Lucene.NET 的搜索,但在尝试搜索本质上是关系数据的内容时遇到了障碍。

在高层次上,我尝试搜索的数据是分组的,每个项目属于 1 到 3 个组。然后,我需要能够搜索组合中的所有项目(例如:每个项目都属于 A 组和 B 组)。

这些分组中的每一个都有我正在搜索的数据中存在的 ID 和描述,但描述可能是彼此的子字符串(例如:一组名为“Stuff”,另一组名为“Other stuff”),并且我不想匹配具有我要查找的子字符串的类别。

我一直在考虑在不进行此过滤的情况下将数据拉回,然后过滤 ID,但出于性能原因,我打算对从 Lucene 返回的数据进行分页。我还考虑过将 ID 以空格分隔并在字段中进行文本搜索,但这似乎完全是 hack...

有谁知道如何在 Lucene.NET 中最好地处理这种搜索? (只是在有人说我使用了错误的工具之前澄清一下,这只是包括全文搜索的更大过滤器集的一个子集。如果您仍然认为我使用了错误的工具,但我很乐意听听哪个是正确的)

【问题讨论】:

    标签: c# lucene.net search


    【解决方案1】:

    我在 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);
        }
    }
    

    该示例将两个未标记化的文档添加到索引中,搜索内容并获得一次命中。如果您更改代码以将它们添加标记化,那么您将有两个命中,如您现在所见。

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

    【讨论】:

    • 您好 HakonB,感谢您的回复。我已经使用 unkenized 进行其他一些查找,但问题是一个项目可以同时存在于“Stuff”和“Other Stuff”中,并且在搜索其中一个或两个时需要找到它。 EG:A 在东西和其他东西 B 在只是东西 C 在只是其他东西 搜索东西 {A,B} 搜索其他东西 {A,C} 搜索东西和其他东西 {A}
    • 我添加了另一个示例来说明如何获得正确的结果 - 如果我现在理解你的话 :-)
    • 啊,谢谢!这似乎正是我所追求的。我从来没有想过我实际上可以将 2 个同名字段添加到 1 个文档中。我猜还是想的太像典型的关系数据库了 =)
    猜你喜欢
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多