package index import ( "encoding/gob" "os" "searchEngine/core/analyzer" "sync" ) type Posting struct { DocId int BodyPositions []int TitlePositions []int } type InvertedIndex struct { Mu sync.RWMutex `gob:"-"` Data map[string][]Posting DocNames map[int]string } func New() *InvertedIndex { return &InvertedIndex{ Data: make(map[string][]Posting), DocNames: make(map[int]string), } } func (idx *InvertedIndex) Add(docID int, title string, bodyTokens []string) { titleTokens := analyzer.ProcessText(title) type fieldStats struct { bodyPositions []int titlePositions []int } docStats := make(map[string]fieldStats) for position, token := range titleTokens { stats := docStats[token] stats.titlePositions = append(stats.titlePositions, position) docStats[token] = stats } for position, token := range bodyTokens { stats := docStats[token] stats.bodyPositions = append(stats.bodyPositions, position) docStats[token] = stats } idx.Mu.Lock() defer idx.Mu.Unlock() idx.DocNames[docID] = title for token, stats := range docStats { idx.Data[token] = append(idx.Data[token], Posting{ DocId: docID, BodyPositions: stats.bodyPositions, TitlePositions: stats.titlePositions, }) } } func (idx *InvertedIndex) Save(filepath string) error { idx.Mu.RLock() defer idx.Mu.RUnlock() file, err := os.Create(filepath) if err != nil { return err } defer file.Close() encoder := gob.NewEncoder(file) return encoder.Encode(idx) } func Load(filepath string) (*InvertedIndex, error) { file, err := os.Open(filepath) if err != nil { return nil, err } defer file.Close() idx := &InvertedIndex{} decoder := gob.NewDecoder(file) err = decoder.Decode(idx) if err != nil { return nil, err } return idx, nil }