我是Lucene的新手。我正在尝试创建记录索引。到目前为止,我一直在向索引添加一对一的数据,这看起来还不错。但是,在某些情况下,我需要将一对多的关系数据相加,并且我不确定什么是最好的处理方式。我尝试添加每个单独的关系,将字段压缩为CSV值,多次添加该字段,但似乎没有任何效果。这是我为数据建立索引的代码:
Private Shared Sub _addToLuceneIndex(ByVal sampleData As LuceneSearchData, ByVal writer As IndexWriter)
Dim searchQuery = New TermQuery(New Term("Id", sampleData.Id.ToString()))
writer.DeleteDocuments(searchQuery)
Dim doc = New Document()
doc.Add(New Field("Id", sampleData.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED))
doc.Add(New Field("Name", sampleData.Name, Field.Store.YES, Field.Index.ANALYZED))
doc.Add(New Field("Description", sampleData.Description, Field.Store.YES, Field.Index.ANALYZED))
For Each item As Integer In sampleData.HomeStates
doc.Add(New Field("Home_State", item, Field.Store.YES, Field.Index.ANALYZED))
Next
'i have also tried
'doc.Add(New Field("HomeStates ", String.Join(",", sampleData.HomeStates ), Field.Store.YES, Field.Index.ANALYZED))
writer.AddDocument(doc)
End Sub
虽然上面的代码似乎索引了一对一数据,但它并不适用于HomeStates整数列表。我是否必须为整数列表中的每个项目添加相同的文档?如果是这样,您如何最好地管理它?我需要包括几个“一对多”关系。我可以看到它很快变得笨拙。还是有更好的方法?
编辑 我更新了将可能值添加为这样的字段:
doc.Add(New Field("Geo_Locations", String.Join(" ", sampleData.Geo_Location), Field.Store.YES, Field.Index.ANALYZED))
这是我搜索该字段的方式:
Private Shared Function _search(ByVal searchQuery As String, ByVal Optional searchField As String = "") As IEnumerable(Of LuceneSearchData)
If String.IsNullOrEmpty(searchQuery.Replace("*", "").Replace("?", "")) Then Return New List(Of LuceneSearchData)()
Using searcher = New IndexSearcher(_directory, False)
Dim hits_limit = 1000
Dim analyzer = New StandardAnalyzer(Version.LUCENE_30)
If Not String.IsNullOrEmpty(searchField) Then
Dim parser = New QueryParser(Version.LUCENE_30, searchField, analyzer)
Dim query = parseQuery(searchQuery, parser)
Dim hits = searcher.Search(query, hits_limit).ScoreDocs
Dim results = _mapLuceneToDataList(hits, searcher)
analyzer.Close()
searcher.Dispose()
Return results
End If
End Using
End Function
Private Shared Function _mapLuceneToDataList(ByVal hits As IEnumerable(Of ScoreDoc), ByVal searcher As IndexSearcher) As IEnumerable(Of LuceneSearchData)
Dim listOfResults As List(Of LuceneSearchData)
Try
listOfResults = hits.[Select](Function(hit) _mapLuceneDocumentToData(searcher.Doc(hit.Doc))).ToList()
Catch ex As Exception
Return Nothing
End Try
Return listOfResults
End Function
Private Shared Function _mapLuceneDocumentToData(ByVal doc As Document) As LuceneSearchData
Return New LuceneSearchData With {
.Id = Convert.ToInt32(doc.[Get]("Id")),
.Mechanism_Name = doc.[Get]("Name"),
.Mechanism_Purpose = doc.[Get]("Description"),
.Geo_Location = doc.[Get]("Home_State")
}
End Function
然后我叫搜索bu:
LuceneData = LuceneSearch.Search("5451", "HomeStates")
答案 0 :(得分:0)
为每个项目创建一个新文档在搜索其他字段时将导致重复。
您应根据需要设计文档和字段。
如果您不需要搜索这些字段,请根据需要存储它们。
如果您需要搜索这些多个值字段,则创建一个可以为每个项目搜索的字段。 对于整数列表,可以将它们与空格合并。 对于字符串列表,在索引和搜索时,应使用一些自定义字符替换空格,以避免匹配子字符串(例如,“堆栈溢出” => stack_overflow)
答案 1 :(得分:0)
您已经发现,可以使用包括空格在内的各种分隔符来连接整数,结果如下:
"234 12342 345 5476456 234"
StandardAnalyzer
会将上面的字符串标记为单独的标记,就像其他任何字符串一样。因此您可以搜索它们,它将为您提供预期的结果。
如果您需要标记短语,例如:
"Control Support Engineer|Technical Support Engineer|Maintenance Technician"
分为单个短语,而不是单词(术语),那么您将需要从几个类中继承。从CharTokenizer
继承的令牌生成器和从Analyzer继承的分析器。
public sealed class PipeTokenizer: CharTokenizer
{
public PipeTokenizer(LuceneVersion matchVersion, TextReader input) :
base(matchVersion, input)
{
}
public PipeTokenizer(LuceneVersion matchVersion, AttributeFactory factory, TextReader input) :
base(matchVersion, factory, input)
{
}
protected override bool IsTokenChar(int c)
{
return !((char)c).Equals('|'); //<-- the only line that matters
}
}
到目前为止,还很简单。
public class PipeAnalyzer: Analyzer
{
protected override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
{
var tokenizer = new PipeTokenizer(LuceneVersion.LUCENE_48, reader);
var lowerCaseFilter = new LowerCaseFilter(LuceneVersion.LUCENE_48, tokenizer);
return new TokenStreamComponents(tokenizer, lowerCaseFilter);
}
}
这基于KeywordAnalyzer
的功能,但有所不同。 KeywordAnalyzer
非常简单。它采用整个字符串或短语,并按原样对其进行索引。没有进一步细分为较小的令牌。上面的分析器使用PipeTokenizer
通过|
分隔符将短语分解,然后转换为小写。
使用以下任何短语查询将返回文档:
"control support engineer"
"technical support engineer"
"maintenance technician"