Добавление одного ко многим данным в индекс Lucene - PullRequest
0 голосов
/ 02 мая 2019

Я новичок в 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. Нужно ли добавлять один и тот же документ для каждого элемента в списке целых чисел? Если так, как вы лучше всего справляетесь с этим? У меня есть несколько отношений «один ко многим», которые мне нужно включить. Я вижу, как это быстро становится громоздким. Или есть способ получше?

EDIT Я обновил, чтобы добавить значение, которое может иметь значение как поле:

 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

Затем я вызываю поиск по номеру:

   LuceneData = LuceneSearch.Search("5451", "HomeStates")

1 Ответ

0 голосов
/ 02 мая 2019

Создание нового документа для каждого элемента приведет к дублированию при поиске других полей.

Вам следует оформить свои документы и поля в соответствии с вашими потребностями.

Если вам не нужночтобы искать эти поля, сохраняйте их по своему желанию.

Если вам необходимо выполнить поиск в этих многозначных полях, создайте поле, в котором можно искать каждый элемент.Для целочисленных списков вы можете объединить их с пробелами.Для строковых списков вы должны заменить пробелы на некоторые пользовательские символы при индексации и поиске, чтобы избежать совпадения подстрок (например, «переполнение стека» => stack_overflow)

...