From b2e05a1d41540586cbaa7c8ee532393501601154 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 29 Jul 2026 00:56:57 +0200 Subject: added proximity based scoring --- .gitignore | 2 +- core/index/index.go | 51 +++++++++++++++++++++++++++++++++++++---------- core/scoring/proximity.go | 31 ++++++++++++++++++++++++++++ core/search/search.go | 15 ++++++++++++++ 4 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 core/scoring/proximity.go diff --git a/.gitignore b/.gitignore index 5f28270..4e71595 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ - \ No newline at end of file +wikipedia_index.gob \ No newline at end of file diff --git a/core/index/index.go b/core/index/index.go index 2e669fc..b00f524 100644 --- a/core/index/index.go +++ b/core/index/index.go @@ -1,6 +1,7 @@ package index import ( + "bufio" "encoding/gob" "os" "searchEngine/core/analyzer" @@ -14,9 +15,10 @@ type Posting struct { } type InvertedIndex struct { - Mu sync.RWMutex `gob:"-"` - Data map[string][]Posting - DocNames map[int]string + Mu sync.RWMutex `gob:"-"` + Data map[string][]Posting + DocNames map[int]string + DocLengths map[int]int } func New() *InvertedIndex { @@ -51,7 +53,7 @@ func (idx *InvertedIndex) Add(docID int, title string, bodyTokens []string) { defer idx.Mu.Unlock() idx.DocNames[docID] = title - + idx.DocLengths[docID] = len(bodyTokens) for token, stats := range docStats { idx.Data[token] = append(idx.Data[token], Posting{ DocId: docID, @@ -71,8 +73,25 @@ func (idx *InvertedIndex) Save(filepath string) error { } defer file.Close() - encoder := gob.NewEncoder(file) - return encoder.Encode(idx) + writer := bufio.NewWriter(file) + + dto := struct { + Data map[string][]Posting + DocNames map[int]string + DocLengths map[int]int + }{ + Data: idx.Data, + DocNames: idx.DocNames, + DocLengths: idx.DocLengths, + } + + encoder := gob.NewEncoder(writer) + err = encoder.Encode(dto) + + if flushErr := writer.Flush(); flushErr != nil { + return flushErr + } + return err } func Load(filepath string) (*InvertedIndex, error) { @@ -82,11 +101,23 @@ func Load(filepath string) (*InvertedIndex, error) { } defer file.Close() - idx := &InvertedIndex{} - decoder := gob.NewDecoder(file) - err = decoder.Decode(idx) + reader := bufio.NewReader(file) + + var dto struct { + Data map[string][]Posting + DocNames map[int]string + DocLengths map[int]int + } + + decoder := gob.NewDecoder(reader) + err = decoder.Decode(&dto) if err != nil { return nil, err } - return idx, nil + + return &InvertedIndex{ + Data: dto.Data, + DocNames: dto.DocNames, + DocLengths: dto.DocLengths, + }, nil } diff --git a/core/scoring/proximity.go b/core/scoring/proximity.go new file mode 100644 index 0000000..f765aa7 --- /dev/null +++ b/core/scoring/proximity.go @@ -0,0 +1,31 @@ +package scoring + +import "math" + +func CalculateProximity(pos1, pos2 []int) float64 { + var score float64 + i, j := 0, 0 + + for i < len(pos1) && j < len(pos2) { + p1 := pos1[i] + p2 := pos2[j] + + dist := math.Abs(float64(p1 - p2)) + + if dist == 1 { + score += 15.0 + } else if dist <= 5 { + score += 5.0 + } else if dist <= 15 { + score += 1.0 + } + + if p1 < p2 { + i++ + } else { + j++ + } + } + + return score +} diff --git a/core/search/search.go b/core/search/search.go index 721574c..cf1054b 100644 --- a/core/search/search.go +++ b/core/search/search.go @@ -24,6 +24,7 @@ func Search(idx *index.InvertedIndex, query string) []string { totalDocs := len(idx.DocNames) docMatchCounts := make(map[int]int) + docPostings := make(map[int][]index.Posting) scores := make(map[int]float64) uniqueMap := make(map[string]bool) @@ -48,6 +49,8 @@ func Search(idx *index.InvertedIndex, query string) []string { docMatchCounts[p.DocId]++ termScore := scoring.ScoreTFIDF(p, idf) scores[p.DocId] += termScore + + docPostings[p.DocId] = append(docPostings[p.DocId], p) } } @@ -57,7 +60,19 @@ func Search(idx *index.InvertedIndex, query string) []string { results = append(results, Result{DocID: docID, Score: scores[docID]}) } } + for i := range results { + proximityBonus := 0.0 + resultsPostings := docPostings[results[i].DocID] + for j := 0; j < len(resultsPostings)-1; j++ { + bodyBonus := scoring.CalculateProximity(resultsPostings[j].BodyPositions, resultsPostings[j+1].BodyPositions) + + titleBonus := scoring.CalculateProximity(resultsPostings[j].TitlePositions, resultsPostings[j+1].TitlePositions) + proximityBonus += bodyBonus + (titleBonus * 5.0) + } + + results[i].Score += proximityBonus + } slices.SortFunc(results, func(a, b Result) int { return cmp.Compare(b.Score, a.Score) }) -- cgit v1.2.3