我有一个Umbraco网站正在使用基于lucene.net的检查搜索。我几乎试图完成以下文章中描述的内容:
Querying against a comma separated list of IDs with Examine and Lucene.Net?
我遇到的问题是当我尝试使用以下代码创建索引时:
// 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"}
}
};
}
我收到以下错误:
已添加具有相同键的项目。
有谁知道如何解决这个问题?
答案 0 :(得分:2)
下一个版本的Examine(v2)将正确支持这一点,任何运气可能会在几个月内消失,但这实际上只取决于我们得到多少时间。
与此同时,您可以在索引器上使用DocumentWriting事件,该事件使您可以直接访问Lucene文档,然后您可以根据需要编制索引。因此,您最初可以为您的类别设置逗号分隔的ID列表,在此活动期间,您可以拆分它们并将它们作为单独的值添加到Lucene中。
答案 1 :(得分:1)
您看到的错误是@DavidH提到的.NET Dictionary<TKey, TValue>
类的限制。限制继承自Examine的SimpleDataSet
类,通过查看source仅允许Dictionary<string, string>
作为向行文档添加行数据的方法。
但是,Lucene Document
允许您添加与链接问题中提到的名称相同的多个字段:
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对这些场景来说更灵活。
答案 2 :(得分:0)
字典键必须是唯一的,这不是特定于Lucene而是特定于.NET Dictionary<TKey, TValue>
类。一种可能的选择是管道分隔一个“类别”字典键下的值,然后拆分管道字符以解析它们:
RowData = new Dictionary<string, string>()
{
{"Name", a.Name},
{"Url", a.NiceUrl},
{"Category", "1234|5678"}
}
然后你可以在管道字符'|'上使用string.Split
解析它们。
答案 3 :(得分:0)
这是在lucene中执行此操作的完整示例,但是正如所述的检查似乎通过在Dictionary中输入来限制灵活性。但是,改变检查来处理它应该很简单。
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);
}
}