Example #1
0
// Range returns one or more records by the specified index within the specified range
func (n *node) Range(fieldName string, min, max, to interface{}, options ...func(*index.Options)) error {
	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.And(q.Gte(fieldName, min), q.Lte(fieldName, max)))

		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()
	}

	mn, err := toBytes(min, n.s.codec)
	if err != nil {
		return err
	}

	mx, err := toBytes(max, n.s.codec)
	if err != nil {
		return err
	}

	return n.readTx(func(tx *bolt.Tx) error {
		return n.rnge(tx, bucketName, fieldName, cfg, sink, mn, mx, opts)
	})
}
Example #2
0
// Select a list of records that match a list of matchers. Doesn't use indexes.
func (n *node) Select(matchers ...q.Matcher) Query {
	tree := q.And(matchers...)
	return newQuery(n, tree)
}