// Find returns one or more records by the specified index func (n *node) Find(fieldName string, value interface{}, to interface{}, options ...func(q *index.Options)) error { if value == nil { return ErrNotFound } sink, err := newListSink(n, to) if err != nil { return err } bucketName := sink.bucketName() if bucketName == "" { return ErrNoName } ref := reflect.Indirect(reflect.New(sink.elemType)) cfg, err := extractSingleField(&ref, fieldName) if err != nil { return err } opts := index.NewOptions() for _, fn := range options { fn(opts) } field, ok := cfg.Fields[fieldName] if !ok || (!field.IsID && field.Index == "") { sink.limit = opts.Limit sink.skip = opts.Skip query := newQuery(n, q.StrictEq(fieldName, value)) if opts.Reverse { query.Reverse() } err = n.readTx(func(tx *bolt.Tx) error { return query.query(tx, sink) }) if err != nil { return err } return sink.flush() } val, err := toBytes(value, n.s.codec) if err != nil { return err } return n.readTx(func(tx *bolt.Tx) error { return n.find(tx, bucketName, fieldName, cfg, sink, val, opts) }) }
// One returns one record by the specified index func (n *node) One(fieldName string, value interface{}, to interface{}) error { sink, err := newFirstSink(n, to) if err != nil { return err } bucketName := sink.bucketName() if bucketName == "" { return ErrNoName } if fieldName == "" { return ErrNotFound } ref := reflect.Indirect(sink.ref) cfg, err := extractSingleField(&ref, fieldName) if err != nil { return err } field, ok := cfg.Fields[fieldName] if !ok || (!field.IsID && field.Index == "") { query := newQuery(n, q.StrictEq(fieldName, value)) if n.tx != nil { err = query.query(n.tx, sink) } else { err = n.s.Bolt.View(func(tx *bolt.Tx) error { return query.query(tx, sink) }) } if err != nil { return err } return sink.flush() } val, err := toBytes(value, n.s.codec) if err != nil { return err } return n.readTx(func(tx *bolt.Tx) error { return n.one(tx, bucketName, fieldName, cfg, to, val, field.IsID) }) }