timshannon / badgerhold

BadgerHold is an embeddable NoSQL store for querying Go types built on Badger
MIT License
514 stars 52 forks source link

reflect: call of reflect.Value.FieldByName on slice Value #111

Closed mybigman closed 1 month ago

mybigman commented 1 month ago
{"data":[{"ID":336010449506554447,"Name":"lev","Age":63,"Kids":[{"Name":"boy","Age":5}]}]}
type data struct {
    ID   uint64 `badgerhold:"key"`
    Name string `badgerholdIndex:"IdxName"`
    Age  int
    Kids []kids
}

type kids struct {
    Name string
    Age  int
}

results := []data{}

err := h.db.Find(&results, badgerhold.Where("Kids.Name").Eq("boy"))

Not sure whats going on here?

timshannon commented 1 month ago

You can only access nested structure fields, not slices.

data.Kids is a slice of Kids. Which kid's name do you want to access the first item in the kids slice? The last?

Here's the code that grabs the field value from your struct:

func fieldValue(value reflect.Value, field string) (reflect.Value, error) {
    fields := strings.Split(field, ".")

    current := value
    for i := range fields {
        if current.Kind() == reflect.Ptr {
            current = current.Elem().FieldByName(fields[i])
        } else {
            current = current.FieldByName(fields[i])
        }
        if !current.IsValid() {
            return reflect.Value{}, fmt.Errorf("The field %s does not exist in the type %s", field, value)
        }
    }
    return current, nil
}