blugelabs / bluge

indexing library for Go
Apache License 2.0
1.9k stars 125 forks source link

How do I access stored fields other than _id ? #56

Open pavel1337 opened 3 years ago

pavel1337 commented 3 years ago

Hi! Just started learning this tool few hours ago. Could not find a way to access stored fields. So I have a slice of objects, it is quite huge, but for example I have added only two here. I can easily get the _id field, but the field name is empty when I try too get it with match.DocValues("name"), or non-existent when I just trying to print all stored fields.

Am I overlooking something here?

Code:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/blugelabs/bluge"
)

type city struct {
    id   string
    name string
}

func main() {
    cities := []city{
        {id: "BER", name: "berlin"},
        {id: "MOW", name: "moscow"},
    }
    cfg := cityBluge(cities)
    findCities(cfg, "ber")
}

func cityBluge(cities []city) *bluge.Config {
    config := bluge.DefaultConfig("cities")
    writer, err := bluge.OpenWriter(config)
    if err != nil {
        log.Fatalf("error opening writer: %v", err)
    }
    defer writer.Close()

    batch := bluge.NewBatch()

    for _, c := range cities {
        doc := bluge.NewDocument(c.id)
        doc.AddField(bluge.NewTextField("name", c.name))
        // batch.Insert(doc)
        batch.Update(doc.ID(), doc)
    }

    err = writer.Batch(batch)
    if err != nil {
        log.Fatalf("error updating document: %v", err)
    }
    return &config
}

func findCities(cfg *bluge.Config, city string) {
    reader, err := bluge.OpenReader(*cfg)
    if err != nil {
        log.Fatalf("error getting index reader: %v", err)
    }
    defer reader.Close()

    query := bluge.NewPrefixQuery(city).SetField("name")
    request := bluge.NewTopNSearch(10, query)
    dmi, err := reader.Search(context.Background(), request)
    if err != nil {
        log.Fatalf("error executing search: %v", err)
    }
    match, err := dmi.Next()
    for err == nil && match != nil {
        bb := match.DocValues("name")
        fmt.Printf("%v\n", bb)
        err = match.VisitStoredFields(func(field string, value []byte) bool {
            fmt.Printf("New match: %s, %s\n", field, string(value))
            return true
        })
        if err != nil {
            log.Fatalf("error loading stored fields: %v", err)
        }
        match, err = dmi.Next()
    }
    if err != nil {
        log.Fatalf("error iterator document matches: %v", err)
    }
}

Output:

user@host:~/bluge-demo$ go run main.go 
[]
New match: _id, BER
mschoch commented 3 years ago

So, DocValues is different from stored values. DocValues are used for sorting and aggregating. Stored values are not used internally by bluge for anything, the only thing we can do is return the back to you.

Your existing use of VisitStoredFields looks correct, it's just that you're not storing the value. You should add a call to StoreValue() when building the field. Something like:

doc.AddField(bluge.NewTextField("name", c.name).StoreValue())
pavel1337 commented 3 years ago

Seems like it is not in the latest available go module which is 0.1.5 for me.

UPD: sorry, overlooked parenthesis order =)

Thank you for the response, going to continue exploring!

prologic commented 2 years ago

I got bitten by this too. I thin the docs and website should be updated to refeclt this. It wasn't obvious to me at first to call .StoreValue() on the fields I'm adding. Thanks!