func (p *InventorySearchUnixTimePropertyInfo) Asc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: true,
	})
	return p.b
}
Asc add query operand.
package e
import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"github.com/favclip/smg/smgutils"
	"google.golang.org/appengine/log"
	"google.golang.org/appengine/search"
	"strconv"
	"time"
)
type InventorySearch struct {
	src *Inventory
	ID                 string
	ProductName        string
	Description        string
	DescriptionUnigram string
	DescriptionBigram  string
	Stock              float64
	Price              string
	Barcode            string
	AdminNames         string
	Shops              string
	CreatedAt          time.Time
	UpdatedAt          time.Time
	UpdatedAtUnixTime  float64
}
func (s *InventorySearch) Load(fields []search.Field, metadata *search.DocumentMetadata) error {
	return search.LoadStruct(s, fields)
}
func (s *InventorySearch) Save() ([]search.Field, *search.DocumentMetadata, error) {
	fields, err := search.SaveStruct(s)
	if err != nil {
		return nil, nil, err
	}
	metadata := &search.DocumentMetadata{Rank: int(s.Stock) + 1}
	return fields, metadata, nil
}
func (src *Inventory) Searchfy() (*InventorySearch, error) {
	if src == nil {
		return nil, nil
	}
	dest := &InventorySearch{}
	dest.src = src
	var err error
	var b []byte
	dest.ID = strconv.FormatInt(src.ID, 10)
	dest.ProductName = src.ProductName
	dest.Description = src.Description
	dest.DescriptionUnigram, err = smgutils.UnigramForSearch(src.Description)
	if err != nil {
		return nil, err
	}
	dest.DescriptionBigram, err = smgutils.BigramForSearch(src.Description)
	if err != nil {
		return nil, err
	}
	dest.Stock = float64(src.Stock)
	dest.Price = strconv.Itoa(src.Price)
	dest.Barcode = strconv.FormatInt(src.Barcode, 10)
	b, err = json.Marshal(src.AdminNames)
	if err != nil {
		return nil, err
	}
	if str := string(b); str != "" && str != "\"\"" {
		dest.AdminNames = str
	}
	b, err = json.Marshal(src.Shops)
	if err != nil {
		return nil, err
	}
	if str := string(b); str != "" && str != "\"\"" {
		dest.Shops = str
	}
	dest.CreatedAt = src.CreatedAt
	dest.UpdatedAtUnixTime = float64(smgutils.Unix(src.UpdatedAt))
	dest.UpdatedAt = src.UpdatedAt
	return dest, nil
}
func NewInventorySearch() *InventorySearchBuilder {
	op := &smgutils.Op{}
	b := &InventorySearchBuilder{
		rootOp:    op,
		currentOp: op,
		opts: &search.SearchOptions{
			Sort: &search.SortOptions{},
		},
	}
	b.ProductName = &InventorySearchStringPropertyInfo{"ProductName", b}
	b.Description = &InventorySearchNgramStringPropertyInfo{InventorySearchStringPropertyInfo{"Description", b}}
	b.Stock = &InventorySearchNumberPropertyInfo{"Stock", b}
	b.Price = &InventorySearchStringPropertyInfo{"Price", b}
	b.Barcode = &InventorySearchStringPropertyInfo{"Barcode", b}
	b.AdminNames = &InventorySearchStringPropertyInfo{"AdminNames", b}
	b.Shops = &InventorySearchStringPropertyInfo{"Shops", b}
	b.CreatedAt = &InventorySearchTimePropertyInfo{"CreatedAt", b}
	b.UpdatedAt = &InventorySearchUnixTimePropertyInfo{"UpdatedAt", b}
	return b
}
func NewInventorySearchWithIndexName(name string) *InventorySearchBuilder {
	b := NewInventorySearch()
	b.indexName = name
	return b
}
var _ smgutils.SearchBuilder = &InventorySearchBuilder{}
type InventorySearchBuilder struct {
	rootOp      *smgutils.Op
	currentOp   *smgutils.Op  
	opts        *search.SearchOptions
	query       string
	indexName   string
	index       *search.Index
	ProductName *InventorySearchStringPropertyInfo
	Description *InventorySearchNgramStringPropertyInfo
	Stock       *InventorySearchNumberPropertyInfo
	Price       *InventorySearchStringPropertyInfo
	Barcode     *InventorySearchStringPropertyInfo
	AdminNames  *InventorySearchStringPropertyInfo
	Shops       *InventorySearchStringPropertyInfo
	CreatedAt   *InventorySearchTimePropertyInfo
	UpdatedAt   *InventorySearchUnixTimePropertyInfo
}
func (b *InventorySearchBuilder) IndexName() string {
	if b.indexName != "" {
		return b.indexName
	}
	return "Inventory"
}
func (b *InventorySearchBuilder) QueryString() (string, error) {
	buffer := &bytes.Buffer{}
	err := b.rootOp.Query(buffer)
	if err != nil {
		return "", err
	}
	return buffer.String(), nil
}
func (b *InventorySearchBuilder) SearchOptions() *search.SearchOptions {
	return b.opts
}
func (b *InventorySearchBuilder) And() *InventorySearchBuilder {
	b.currentOp.Children = append(b.currentOp.Children, &smgutils.Op{Type: smgutils.And})
	return b
}
func (b *InventorySearchBuilder) Or() *InventorySearchBuilder {
	b.currentOp.Children = append(b.currentOp.Children, &smgutils.Op{Type: smgutils.Or})
	return b
}
func (b *InventorySearchBuilder) Group(p func()) *InventorySearchBuilder {
	b.StartGroup()
	p()
	b.EndGroup()
	return b
}
func (b *InventorySearchBuilder) StartGroup() *InventorySearchBuilder {
	op := &smgutils.Op{Type: smgutils.Group, Parent: b.currentOp}
	b.currentOp.Children = append(b.currentOp.Children, op)
	b.currentOp = op
	return b
}
func (b *InventorySearchBuilder) EndGroup() *InventorySearchBuilder {
	b.currentOp = b.currentOp.Parent
	return b
}
func (b *InventorySearchBuilder) Put(c context.Context, src *Inventory) (string, error) {
	doc, err := src.Searchfy()
	if err != nil {
		return "", err
	}
	return b.PutDocument(c, doc)
}
func (b *InventorySearchBuilder) PutMulti(c context.Context, srcs []*Inventory) ([]string, error) {
	docs := make([]*InventorySearch, 0, len(srcs))
	for _, src := range srcs {
		doc, err := src.Searchfy()
		if err != nil {
			return nil, err
		}
		docs = append(docs, doc)
	}
	return b.PutDocumentMulti(c, docs)
}
func (b *InventorySearchBuilder) PutDocument(c context.Context, src *InventorySearch) (string, error) {
	docIDs, err := b.PutDocumentMulti(c, []*InventorySearch{src})
	if err != nil {
		return "", err
	}
	return docIDs[0], nil
}
func (b *InventorySearchBuilder) PutDocumentMulti(c context.Context, srcs []*InventorySearch) ([]string, error) {
	index, err := search.Open(b.IndexName())
	if err != nil {
		return nil, err
	}
	docIDs := make([]string, 0, len(srcs))
	putSrcs := make([]interface{}, 0, len(srcs))
	for _, src := range srcs {
		docID := ""
		if v, ok := interface{}(src).(smgutils.DocIDer); ok {
			docID, err = v.DocID(c)
			if err != nil {
				return nil, err
			}
			src.ID = docID
		}
		docIDs = append(docIDs, docID)
		putSrcs = append(putSrcs, src)
		log.Debugf(c, "id: %#v, payload: %#v", docID, src)
	}
	docIDs, err = index.PutMulti(c, docIDs, putSrcs)
	if err != nil {
		return nil, err
	}
	for idx, docID := range docIDs {
		srcs[idx].ID = docID
	}
	return docIDs, nil
}
func (b *InventorySearchBuilder) Delete(c context.Context, src *Inventory) error {
	doc, err := src.Searchfy()
	if err != nil {
		return err
	}
	return b.DeleteDocument(c, doc)
}
func (b *InventorySearchBuilder) DeleteMulti(c context.Context, srcs []*Inventory) error {
	docs := make([]*InventorySearch, 0, len(srcs))
	for _, src := range srcs {
		doc, err := src.Searchfy()
		if err != nil {
			return err
		}
		docs = append(docs, doc)
	}
	return b.DeleteDocumentMulti(c, docs)
}
func (b *InventorySearchBuilder) DeleteDocument(c context.Context, src *InventorySearch) error {
	return b.DeleteDocumentMulti(c, []*InventorySearch{src})
}
func (b *InventorySearchBuilder) DeleteDocumentMulti(c context.Context, srcs []*InventorySearch) error {
	docIDs := make([]string, 0, len(srcs))
	for _, src := range srcs {
		if v, ok := interface{}(src).(smgutils.DocIDer); ok {
			docID, err := v.DocID(c)
			if err != nil {
				return err
			}
			docIDs = append(docIDs, docID)
			continue
		}
		return errors.New("src is not implemented DocIDer interface")
	}
	return b.DeleteMultiByDocIDs(c, docIDs)
}
func (b *InventorySearchBuilder) DeleteByDocID(c context.Context, docID string) error {
	return b.DeleteMultiByDocIDs(c, []string{docID})
}
func (b *InventorySearchBuilder) DeleteMultiByDocIDs(c context.Context, docIDs []string) error {
	index, err := search.Open(b.IndexName())
	if err != nil {
		return err
	}
	return index.DeleteMulti(c, docIDs)
}
func (b *InventorySearchBuilder) Opts() *InventorySearchOptions {
	return &InventorySearchOptions{b: b}
}
func (b *InventorySearchBuilder) Search(c context.Context) (*InventorySearchIterator, error) {
	index, err := search.Open(b.IndexName())
	if err != nil {
		return nil, err
	}
	b.index = index
	query, err := b.QueryString()
	if err != nil {
		return nil, err
	}
	b.query = query
	log.Debugf(c, "query: '%s', opts: %#v", b.query, b.opts)
	iter := b.index.Search(c, b.query, b.opts)
	return &InventorySearchIterator{b, iter}, nil
}
type InventorySearchOptions struct {
	b *InventorySearchBuilder
}
func (b *InventorySearchOptions) Limit(value int) *InventorySearchOptions {
	b.b.opts.Limit = value
	return b
}
func (b *InventorySearchOptions) IDsOnly() *InventorySearchOptions {
	b.b.opts.IDsOnly = true
	return b
}
func (b *InventorySearchOptions) Cursor(cursor search.Cursor) *InventorySearchOptions {
	b.b.opts.Cursor = cursor
	return b
}
func (b *InventorySearchOptions) Offset(value int) *InventorySearchOptions {
	b.b.opts.Offset = value
	return b
}
type InventorySearchIterator struct {
	b    *InventorySearchBuilder
	iter *search.Iterator
}
func (b *InventorySearchIterator) Next(c context.Context) (string, *InventorySearch, error) {
	var s *InventorySearch
	if b.b.opts == nil || b.b.opts.IDsOnly != true {
		s = &InventorySearch{}
	}
	docID, err := b.iter.Next(s)
	if err != nil {
		return "", nil, err
	}
	if s != nil {
		s.ID = docID
	}
	return docID, s, err
}
func (b *InventorySearchIterator) Cursor() search.Cursor {
	return b.iter.Cursor()
}
type InventorySearchStringPropertyInfo struct {
	Name string
	b    *InventorySearchBuilder
}
func (p *InventorySearchStringPropertyInfo) Match(value string) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Match, Value: value})
	return p.b
}
func (p *InventorySearchStringPropertyInfo) Asc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: true,
	})
	return p.b
}
func (p *InventorySearchStringPropertyInfo) Desc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: false,
	})
	return p.b
}
type InventorySearchNgramStringPropertyInfo struct {
	InventorySearchStringPropertyInfo
}
func (p *InventorySearchNgramStringPropertyInfo) NgramMatch(value string) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.NgramMatch, Value: value})
	return p.b
}
type InventorySearchNumberPropertyInfo struct {
	Name string
	b    *InventorySearchBuilder
}
func (p *InventorySearchNumberPropertyInfo) IntGreaterThanOrEqual(value int) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) IntGreaterThan(value int) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) IntLessThanOrEqual(value int) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) IntLessThan(value int) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) IntEqual(value int) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Int64GreaterThanOrEqual(value int64) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Int64GreaterThan(value int64) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Int64LessThanOrEqual(value int64) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Int64LessThan(value int64) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Int64Equal(value int64) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Asc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: true,
	})
	return p.b
}
func (p *InventorySearchNumberPropertyInfo) Desc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: false,
	})
	return p.b
}
type InventorySearchBoolPropertyInfo struct {
	Name string
	b    *InventorySearchBuilder
}
func (p *InventorySearchNumberPropertyInfo) Equal(value bool) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value})
	return p.b
}
type InventorySearchTimePropertyInfo struct {
	Name string
	b    *InventorySearchBuilder
}
func (p *InventorySearchTimePropertyInfo) GreaterThanOrEqual(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchTimePropertyInfo) GreaterThan(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchTimePropertyInfo) LessThanOrEqual(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchTimePropertyInfo) LessThan(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchTimePropertyInfo) Equal(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchTimePropertyInfo) Asc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: true,
	})
	return p.b
}
func (p *InventorySearchTimePropertyInfo) Desc() *InventorySearchBuilder {
	if p.b.opts == nil {
		p.b.opts = &search.SearchOptions{}
	}
	if p.b.opts.Sort == nil {
		p.b.opts.Sort = &search.SortOptions{}
	}
	p.b.opts.Sort.Expressions = append(p.b.opts.Sort.Expressions, search.SortExpression{
		Expr:    p.Name,
		Reverse: false,
	})
	return p.b
}
type InventorySearchUnixTimePropertyInfo struct {
	Name string
	b    *InventorySearchBuilder
}
func (p *InventorySearchUnixTimePropertyInfo) GreaterThanOrEqual(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchUnixTimePropertyInfo) GreaterThan(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchUnixTimePropertyInfo) LessThanOrEqual(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchUnixTimePropertyInfo) LessThan(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value.UTC()})
	return p.b
}
func (p *InventorySearchUnixTimePropertyInfo) Equal(value time.Time) *InventorySearchBuilder {
	p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value.UTC()})
	return p.b
}