package index import ( "bufio" "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 DocLengths map[int]int } 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 idx.DocLengths[docID] = len(bodyTokens) 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() 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) { file, err := os.Open(filepath) if err != nil { return nil, err } defer file.Close() 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 &InvertedIndex{ Data: dto.Data, DocNames: dto.DocNames, DocLengths: dto.DocLengths, }, nil }