2

我有一个使用基于 lucene.net 的检查搜索的 Umbraco 网站。我非常想完全按照以下文章中的描述进行操作:

使用 Examine 和 Lucene.Net 查询逗号分隔的 ID 列表?

我遇到的问题是当我尝试使用以下代码创建索引时:

// Loop through articles
        foreach (var a in articles)
        {
            yield return new SimpleDataSet()
            {
                NodeDefinition = new Examine.IndexedNode()
                {
                    NodeId = a.Id,
                    Type = "Article"

                },
                RowData = new Dictionary<string, string>()
                {
                    {"Name", a.Name},
                    {"Url", a.NiceUrl},
                    {"Category", "1234"},
                    {"Category", "5678"}
                }
            };
        }

我收到以下错误:

已添加具有相同密钥的项目。

有谁知道我该如何解决这个问题?

4

4 回答 4

2

下一个版本的检查 (v2) 将适当地支持这一点,任何运气都可能在几个月内出现,但这实际上取决于我们有多少时间。

同时,您可以在您的索引器上使用 DocumentWriting 事件,它可以让您直接访问 Lucene 文档,然后您可以随意索引。因此,您最初可以为您的类别创建一个逗号分隔的 id 列表,在此事件中,您可以拆分它们并将它们作为单独的值添加到 Lucene 中。

于 2014-08-05T17:21:07.643 回答
1

您看到的错误是Dictionary<TKey, TValue>@DavidH 提到的.NET 类的限制。该限制继承自 Examine 的SimpleDataSet类,通过查看源代码,该类仅允许Dictionary<string, string>将行数据添加到文档中。

但是,LuceneDocument 确实允许您添加与链接问题中提到的名称相同的多个字段:

using Lucene.Net.Documents;

var document = new Document();
document.Add(CreateField("Id", a.Id));
document.Add(CreateField("Name", a.Name));
document.Add(CreateField("Url", a.NiceUrl));        
document.Add(CreateField("Category", "1234"));    
document.Add(CreateField("Category", "5678"));    

...

private Field CreateField(string fieldName, string fieldValue)
{
    return new Field(
        fieldName, 
        fieldValue, 
        Field.Store.YES, 
        Field.Index.ANALYZED);
}

虽然不如 Examine 的 API 方便,但在这些场景中,原生使用 Lucene 更加灵活。

于 2013-05-31T14:41:24.407 回答
0

这是在 lucene 中执行此操作的完整示例,但是正如所述检查似乎通过在字典中输入来限制灵活性。但是更改检查来处理它应该很简单。

public static void Main (string[] args)
    {
        Analyzer analyser = new StandardAnalyzer (Lucene.Net.Util.Version.LUCENE_CURRENT);
        Directory dir = new RAMDirectory ();

        using (IndexWriter iw = new IndexWriter (dir, analyser, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED)) {

            Document doc1 = new Document ();
            doc1.Add (new Field("title", "multivalued", Field.Store.YES, Field.Index.ANALYZED));
            doc1.Add (new Field("multival", "val1", Field.Store.YES, Field.Index.ANALYZED));
            doc1.Add (new Field("multival", "val2", Field.Store.YES, Field.Index.ANALYZED));
            iw.AddDocument (doc1);
            Document doc2 = new Document ();
            doc2.Add (new Field("title", "singlevalued", Field.Store.YES, Field.Index.ANALYZED));
            doc2.Add (new Field("multival", "val1", Field.Store.YES, Field.Index.ANALYZED));        
            iw.AddDocument (doc2);
        }

        using (Searcher searcher = new IndexSearcher (dir, true)) {
            var q1 = new TermQuery (new Term ("multival", "val1"));
            var q1result = searcher.Search (q1, 1000);

            //Will print "Found 2 documents"
            Console.WriteLine ("Found {0} documents", q1result.TotalHits);

            var q2 = new TermQuery (new Term ("multival", "val2"));
            var q2result = searcher.Search (q2, 1000);
            //Will print "Found 1 documents"
            Console.WriteLine ("Found {0} documents", q2result.TotalHits);
        }
    }
于 2013-05-31T16:13:37.877 回答
0

字典键必须是唯一的,这不是特定于 Lucene 而是特定于 .NETDictionary<TKey, TValue>类。一种可能的选择是用管道分隔一个“类别”字典键下的值,然后在管道字符上拆分以解析它们:

RowData = new Dictionary<string, string>()
{
    {"Name", a.Name},
    {"Url", a.NiceUrl},
    {"Category", "1234|5678"}
}

然后您可以string.Split在管道字符上使用“|” 将它们解析出来。

于 2013-05-29T15:34:37.757 回答