Example #1
0
func (st *BuildStruct) emit(g *genbase.Generator) error {
	g.Printf("// %[1]sQueryBuilder build query for %[1]s.\n", st.Name())

	// generate FooQueryBuilder struct from Foo struct
	g.Printf("type %sQueryBuilder struct {\n", st.Name())
	g.Printf("q *datastore.Query\n")
	g.Printf("plugin qbgutils.Plugin\n")

	for _, field := range st.Fields {
		if field.Tag.Ignore {
			continue
		}

		g.Printf("%[1]s *%[2]sQueryProperty\n", field.Tag.PropertyNameAlter, st.Name())
	}
	g.Printf("}\n\n")

	// generate property info
	g.Printf(`
			// %[1]sQueryProperty has property information for %[1]sQueryBuilder.
			type %[1]sQueryProperty struct {
				bldr *%[1]sQueryBuilder
				name string
			}

			`, st.Name())

	// generate new query builder factory function
	g.Printf("// New%[1]sQueryBuilder create new %[1]sQueryBuilder.\n", st.Name())
	g.Printf("func New%[1]sQueryBuilder() *%[1]sQueryBuilder {\n", st.Name())
	g.Printf("return New%[1]sQueryBuilderWithKind(\"%[2]s\")\n", st.Name(), st.Kind())
	g.Printf("}\n\n")

	g.Printf("// New%[1]sQueryBuilderWithKind create new %[1]sQueryBuilder with specific kind.\n", st.Name())
	g.Printf("func New%[1]sQueryBuilderWithKind(kind string) *%[1]sQueryBuilder {\n", st.Name())
	g.Printf("q := datastore.NewQuery(kind)\n")
	g.Printf("bldr := &%[1]sQueryBuilder{q:q}\n", st.Name())
	for _, field := range st.Fields {
		if field.Tag.Ignore {
			continue
		}
		name := field.Tag.Name
		if field.Tag.ID {
			name = "__key__"
		}
		g.Printf(`bldr.%[2]s= &%[1]sQueryProperty{
						bldr : bldr,
						name: "%[3]s",
					}
			`, st.Name(), field.Tag.PropertyNameAlter, name)
	}
	g.Printf(`
			if plugger, ok := interface{}(bldr).(qbgutils.Plugger); ok {
				bldr.plugin = plugger.Plugin()
				bldr.plugin.Init("%[1]s")
			}
			`, st.Name())
	g.Printf("return bldr\n")
	g.Printf("}\n\n")

	// generate methods
	g.Printf(`
			// Ancestor sets parent key to ancestor query.
			func (bldr *%[1]sQueryBuilder) Ancestor(parentKey *datastore.Key) *%[1]sQueryBuilder {
				bldr.q = bldr.q.Ancestor(parentKey)
				if bldr.plugin != nil {
					bldr.plugin.Ancestor(parentKey)
				}
				return bldr
			}

			// KeysOnly sets keys only option to query.
			func (bldr *%[1]sQueryBuilder) KeysOnly() *%[1]sQueryBuilder {
				bldr.q = bldr.q.KeysOnly()
				if bldr.plugin != nil {
					bldr.plugin.KeysOnly()
				}
				return bldr
			}

			// Start setup to query.
			func (bldr *%[1]sQueryBuilder) Start(cur datastore.Cursor) *%[1]sQueryBuilder {
				bldr.q = bldr.q.Start(cur)
				if bldr.plugin != nil {
					bldr.plugin.Start(cur)
				}
				return bldr
			}

			// Offset setupto query.
			func (bldr *%[1]sQueryBuilder) Offset(offset int) *%[1]sQueryBuilder {
				bldr.q = bldr.q.Offset(offset)
				if bldr.plugin != nil {
					bldr.plugin.Offset(offset)
				}
				return bldr
			}

			// Limit setup to query.
			func (bldr *%[1]sQueryBuilder) Limit(limit int) *%[1]sQueryBuilder {
				bldr.q = bldr.q.Limit(limit)
				if bldr.plugin != nil {
					bldr.plugin.Limit(limit)
				}
				return bldr
			}

			// Query returns *datastore.Query.
			func (bldr *%[1]sQueryBuilder) Query() *datastore.Query {
				return bldr.q
			}

			// Filter with op & value.
			func (p *%[1]sQueryProperty) Filter(op string, value interface{}) *%[1]sQueryBuilder {
				switch op {
					case "<=":
						p.LessThanOrEqual(value)
					case ">=":
						p.GreaterThanOrEqual(value)
					case "<":
						p.LessThan(value)
					case ">":
						p.GreaterThan(value)
					case "=":
						p.Equal(value)
					default:
						p.bldr.q = p.bldr.q.Filter(p.name + " " + op, value) // error raised by native query
				}
				if p.bldr.plugin != nil {
					p.bldr.plugin.Filter(p.name, op, value)
				}
				return p.bldr
			}

			// LessThanOrEqual filter with value.
			func (p *%[1]sQueryProperty) LessThanOrEqual(value interface{}) *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Filter(p.name + " <=", value)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Filter(p.name,"<=", value)
				}
				return p.bldr
			}

			// GreaterThanOrEqual filter with value.
			func (p *%[1]sQueryProperty) GreaterThanOrEqual(value interface{}) *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Filter(p.name +  " >=", value)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Filter(p.name,">=", value)
				}
				return p.bldr
			}

			// LessThan filter with value.
			func (p *%[1]sQueryProperty) LessThan(value interface{}) *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Filter(p.name + " <", value)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Filter(p.name,"<", value)
				}
				return p.bldr
			}

			// GreaterThan filter with value.
			func (p *%[1]sQueryProperty) GreaterThan(value interface{}) *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Filter(p.name + " >", value)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Filter(p.name,">", value)
				}
				return p.bldr
			}

			// Equal filter with value.
			func (p *%[1]sQueryProperty) Equal(value interface{}) *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Filter(p.name + " =", value)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Filter(p.name,"=", value)
				}
				return p.bldr
			}

			// Asc order.
			func (p *%[1]sQueryProperty) Asc() *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Order(p.name)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Asc(p.name)
				}
				return p.bldr
			}

			// Desc order.
			func (p *%[1]sQueryProperty) Desc() *%[1]sQueryBuilder {
				p.bldr.q = p.bldr.q.Order("-" + p.name)
				if p.bldr.plugin != nil {
					p.bldr.plugin.Desc(p.name)
				}
				return p.bldr
			}
		`, st.Name(), "%s")

	g.Printf("\n\n")

	return nil
}
Example #2
0
func (st *BuildStruct) emit(g *genbase.Generator) error {
	g.Printf("// %[1]sSearch best match Search API wrapper for %[1]s.\n", st.Name())

	// generate FooJson struct from Foo struct
	g.Printf("type %sSearch struct {\n", st.Name())
	g.Printf("src *%s\n\n", st.Name())
	for _, field := range st.Fields {
		if field.Tag.Ignore {
			continue
		}
		if field.Tag.ID {
			g.Printf("%[1]s string\n", field.Name)
		} else if field.Tag.Ngram {
			g.Printf("%[1]s string\n", field.Name, st.Name())
			g.Printf("%[1]sUnigram string\n", field.Name, st.Name())
			g.Printf("%[1]sBigram string\n", field.Name, st.Name())
		} else if field.Tag.String {
			g.Printf("%[1]s string\n", field.Name, st.Name())
		} else if field.Tag.JSON {
			g.Printf("%[1]s string\n", field.Name, st.Name())
		} else if field.fieldInfo.IsNumber() {
			g.Printf("%[1]s float64\n", field.Name, st.Name())
		} else if field.fieldInfo.IsBool() {
			g.Printf("%[1]s float64 // 1(true) or 0(false)\n", field.Name, st.Name())
		} else if field.Tag.UnixTime {
			g.Printf("%[1]s time.Time\n", field.Name, st.Name())
			g.Printf("%[1]sUnixTime float64\n", field.Name, st.Name())
		} else if field.fieldInfo.IsTime() {
			g.Printf("%[1]s time.Time\n", field.Name, st.Name())
		} else if field.fieldInfo.IsString() {
			g.Printf("%[1]s string\n", field.Name, st.Name())
		} else {
			return fmt.Errorf("%s: unknown field type in %s", field.Name, st.Name())
		}
	}
	g.Printf("}\n\n")

	// implement DocumentMetadata
	rank := st.Rank()
	if rank != nil {
		g.Printf(`
				// Load by search.LoadStruct.
				func (s *%[1]sSearch) Load(fields []search.Field, metadata *search.DocumentMetadata) error {
					return search.LoadStruct(s, fields)
				}

				// Save with search.DocumentMetadata#Rank.
				func (s *%[1]sSearch) Save() ([]search.Field, *search.DocumentMetadata, error) {
					fields, err := search.SaveStruct(s)
					if err != nil {
						return nil, nil, err
					}
					// https://cloud.google.com/appengine/docs/go/search/reference#DocumentMetadata
					// 0 origin value can not be correctly sorted.
					// Typically, the data is assumed to be 0's origin, 1 added every time.
					metadata := &search.DocumentMetadata{Rank: int(s.%[2]s) + 1}

					return fields, metadata, nil
				}
			`, st.Name(), rank.Name)
	}

	// implement Searchfy method
	g.Printf(`
			// Searchfy converts *%[1]s to *%[1]sSearch.
			func (src *%[1]s) Searchfy() (*%[1]sSearch, error) {
				if src == nil {
					return nil, nil
				}
				dest := &%[1]sSearch{}
				dest.src = src
		`, st.Name())

	if st.HasJSON() {
		g.Printf("var err error\n")
		g.Printf("var b []byte\n")
	} else if st.HasNgram() {
		g.Printf("var err error\n")
	}

	for _, field := range st.Fields {
		if field.Tag.Ignore {
			continue
		}
		if field.Tag.ID || field.Tag.String {
			if field.fieldInfo.IsInt64() {
				g.Printf("dest.%[1]s = strconv.FormatInt(src.%[1]s, 10)\n", field.Name)
			} else if field.fieldInfo.IsInt() {
				g.Printf("dest.%[1]s = strconv.Itoa(src.%[1]s)\n", field.Name)
			} else if field.fieldInfo.IsString() {
				g.Printf("dest.%[1]s = src.%[1]s\n", field.Name)
			} else {
				// TODO support float32, float64
				return fmt.Errorf("%s: id field should be int64, int, or string", field.Name)
			}

		} else if field.Tag.Ngram {
			if field.fieldInfo.IsString() {
				g.Printf(`
						dest.%[1]s = src.%[1]s
						dest.%[1]sUnigram, err = smgutils.UnigramForSearch(src.%[1]s)
						if err != nil {
							return nil, err
						}
						dest.%[1]sBigram, err = smgutils.BigramForSearch(src.%[1]s)
						if err != nil {
							return nil, err
						}
					`, field.Name)
			} else {
				return fmt.Errorf("%s: ngram field should be string", field.Name)
			}
		} else if field.Tag.JSON {
			g.Printf(`
					b, err = json.Marshal(src.%[1]s)
					if err != nil {
						return nil, err
					}
					if str := string(b); str != "" && str != "\"\"" {
						dest.%[1]s = str
					}
				`, field.Name)
		} else if field.Tag.UnixTime {
			if field.fieldInfo.IsTime() {
				g.Printf(`
						dest.%[1]sUnixTime = float64(smgutils.Unix(src.%[1]s))
						dest.%[1]s = src.%[1]s
					`, field.Name)
			} else {
				return fmt.Errorf("%s: unixtime field should be time.Time", field.Name)
			}
		} else {
			// TODO implement invalid type detection
			if field.fieldInfo.IsInt64() || field.fieldInfo.IsInt() || field.fieldInfo.IsFloat32() {
				g.Printf("dest.%[1]s = float64(src.%[1]s)\n", field.Name)
			} else if field.fieldInfo.IsBool() {
				g.Printf(`if src.%[1]s {
							dest.%[1]s = 1
						} else {
							dest.%[1]s = 0
						}
					`, field.Name)
			} else if field.fieldInfo.IsString() || field.fieldInfo.IsFloat64() || field.fieldInfo.IsTime() {
				g.Printf("dest.%[1]s = src.%[1]s\n", field.Name)
			} else {
				return fmt.Errorf("%s: unknown field type in %s", field.Name, st.Name())
			}
		}
	}
	g.Printf("return dest, nil\n}\n\n")

	// implement New*Search method
	g.Printf(`
			// New%[1]sSearch create new *%[1]sSearchBuilder.
			func New%[1]sSearch() *%[1]sSearchBuilder {
				op := &smgutils.Op{}
				b := &%[1]sSearchBuilder{
					rootOp:    op,
					currentOp: op,
					opts: &search.SearchOptions{
						Sort: &search.SortOptions {},
					},
				}
		`, st.Name())

	for _, field := range st.Fields {
		if field.Tag.ID || field.Tag.Ignore {
			continue
		} else if field.Tag.Ngram {
			g.Printf("b.%[1]s = &%[2]sSearchNgramStringPropertyInfo{%[2]sSearchStringPropertyInfo{\"%[1]s\", b}}\n", field.Name, st.Name())
		} else if field.fieldInfo.IsString() || field.Tag.JSON || field.Tag.String {
			g.Printf("b.%[1]s = &%[2]sSearchStringPropertyInfo{\"%[1]s\", b}\n", field.Name, st.Name())
		} else if field.fieldInfo.IsNumber() || field.fieldInfo.IsBool() {
			// special support to bool
			g.Printf("b.%[1]s = &%[2]sSearchNumberPropertyInfo{\"%[1]s\", b}\n", field.Name, st.Name())
		} else if field.Tag.UnixTime {
			g.Printf("b.%[1]s = &%[2]sSearchUnixTimePropertyInfo{\"%[1]s\", b}\n", field.Name, st.Name())
		} else if field.fieldInfo.IsTime() {
			g.Printf("b.%[1]s = &%[2]sSearchTimePropertyInfo{\"%[1]s\", b}\n", field.Name, st.Name())
		} else {
			return fmt.Errorf("%s: unknown field type in %s", field.Name, st.Name())
		}
	}
	g.Printf(`
				return b
			}
		`)

	// implement *SearchBuilder struct
	g.Printf(`
			var _ smgutils.SearchBuilder = &%[1]sSearchBuilder{}

			// %[1]sSearchBuilder builds Search API query.
			type %[1]sSearchBuilder struct {
				rootOp      *smgutils.Op
				currentOp   *smgutils.Op // for grouping
				opts        *search.SearchOptions
				query       string
				index       *search.Index
		`, st.Name())
	for _, field := range st.Fields {
		if field.Tag.ID || field.Tag.Ignore {
			continue
		} else if field.Tag.Ngram {
			g.Printf("%[1]s *%[2]sSearchNgramStringPropertyInfo\n", field.Name, st.Name())
		} else if field.fieldInfo.IsString() || field.Tag.JSON || field.Tag.String {
			g.Printf("%[1]s *%[2]sSearchStringPropertyInfo\n", field.Name, st.Name())
		} else if field.fieldInfo.IsNumber() || field.fieldInfo.IsBool() {
			// TODO special support to bool
			g.Printf("%[1]s *%[2]sSearchNumberPropertyInfo\n", field.Name, st.Name())
		} else if field.Tag.UnixTime {
			g.Printf("%[1]s *%[2]sSearchUnixTimePropertyInfo\n", field.Name, st.Name())
		} else if field.fieldInfo.IsTime() {
			g.Printf("%[1]s *%[2]sSearchTimePropertyInfo\n", field.Name, st.Name())
		} else {
			return fmt.Errorf("%s: unknown field type in %s", field.Name, st.Name())
		}
	}
	g.Printf("}\n\n")

	// implement SearchBuilder methods and others
	g.Printf(`
			// IndexName returns name of target index.
			func (b *%[1]sSearchBuilder) IndexName() string {
				return "%[1]s"
			}

			// QueryString returns query string.
			func (b *%[1]sSearchBuilder) QueryString() (string, error) {
				buffer := &bytes.Buffer{}
				err := b.rootOp.Query(buffer)
				if err != nil {
					return "", err
				}
				return buffer.String(), nil
			}

			// SearchOptions returns search options.
			func (b *%[1]sSearchBuilder) SearchOptions() *search.SearchOptions {
				return b.opts
			}

			// And append new operant to query.
			func (b *%[1]sSearchBuilder) And() *%[1]sSearchBuilder {
				b.currentOp.Children = append(b.currentOp.Children, &smgutils.Op{Type: smgutils.And})
				return b
			}

			// Or append new operant to query.
			func (b *%[1]sSearchBuilder) Or() *%[1]sSearchBuilder {
				b.currentOp.Children = append(b.currentOp.Children, &smgutils.Op{Type: smgutils.Or})
				return b
			}

			// Group append new operant to query.
			func (b *%[1]sSearchBuilder) Group(p func()) *%[1]sSearchBuilder {
				b.StartGroup()
				p()
				b.EndGroup()
				return b
			}

			// StartGroup append new operant to query.
			func (b *%[1]sSearchBuilder) StartGroup() *%[1]sSearchBuilder {
				op := &smgutils.Op{Type: smgutils.Group, Parent: b.currentOp}
				b.currentOp.Children = append(b.currentOp.Children, op)
				b.currentOp = op
				return b
			}

			// EndGroup append new operant to query.
			func (b *%[1]sSearchBuilder) EndGroup() *%[1]sSearchBuilder {
				b.currentOp = b.currentOp.Parent
				return b
			}

			// Put document to Index.
			func (b *%[1]sSearchBuilder) Put(c context.Context, src *%[1]s) (string, error) {
				doc, err := src.Searchfy()
				if err != nil {
					return "", err
				}
				return b.PutDocument(c, doc)
			}

			// PutDocument to Index.
			func (b *%[1]sSearchBuilder) PutDocument(c context.Context, src *%[1]sSearch) (string, error) {
				index, err := search.Open(b.IndexName())
				if err != nil {
					return "", err
				}

				docID := ""
				if v, ok := interface{}(src).(smgutils.DocIDer); ok { // TODO can I shorten this cond expression?
					docID, err = v.DocID(c)
					if err != nil {
						return "", err
					}
			`, st.Name(), "%")
	if st.HasID() {
		g.Printf("src.ID = docID")
	}
	g.Printf(`
				}

				log.Debugf(c, "id: %[2]s#v, payload: %[2]s#v", docID, src)

				docID, err = index.Put(c, docID, src)
				if err != nil {
					return "", err
				}

			`, st.Name(), "%")
	if st.HasID() {
		g.Printf("src.ID = docID")
	}
	g.Printf(`

				return docID, nil
			}

			// Delete document from Index.
			func (b *%[1]sSearchBuilder) Delete(c context.Context, src *%[1]s) error {
				doc, err := src.Searchfy()
				if err != nil {
					return err
				}
				return b.DeleteDocument(c, doc)
			}

			// DeleteDocument from Index.
			func (b *%[1]sSearchBuilder) DeleteDocument(c context.Context, src *%[1]sSearch) error {
				if v, ok := interface{}(src).(smgutils.DocIDer); ok { // TODO can I shorten this cond expression?
					docID, err := v.DocID(c)
					if err != nil {
						return err
					}
					return b.DeleteByDocID(c, docID)
				}

				return errors.New("src is not implemented DocIDer interface")
			}

			// DeleteByDocID from Index.
			func (b *%[1]sSearchBuilder) DeleteByDocID(c context.Context, docID string) error {
				index, err := search.Open(b.IndexName())
				if err != nil {
					return err
				}

				return index.Delete(c, docID)
			}

			// Opts returns *%[1]sSearchOptions.
			func (b *%[1]sSearchBuilder) Opts() *%[1]sSearchOptions {
				return &%[1]sSearchOptions{b: b}
			}

			// Search returns *%[1]sSearchIterator, It is result from Index.
			func (b *%[1]sSearchBuilder) Search(c context.Context) (*%[1]sSearchIterator, 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: '%[2]ss', opts: %[2]s#v", b.query, b.opts)
				iter := b.index.Search(c, b.query, b.opts)

				return &%[1]sSearchIterator{b, iter}, nil
			}

			// %[1]sSearchOptions construct *search.SearchOptions.
			type %[1]sSearchOptions struct {
				b *%[1]sSearchBuilder
			}

			// Limit setup opts.
			func (b *%[1]sSearchOptions) Limit(value int) *%[1]sSearchOptions {
				b.b.opts.Limit = value
				return b
			}

			// IDsOnly setup opts.
			func (b *%[1]sSearchOptions) IDsOnly() *%[1]sSearchOptions {
				b.b.opts.IDsOnly = true
				return b
			}

			// Cursor setup opts.
			func (b *%[1]sSearchOptions) Cursor(cursor search.Cursor) *%[1]sSearchOptions {
				b.b.opts.Cursor = cursor
				return b
			}

			// Offset setup opts.
			func (b *%[1]sSearchOptions) Offset(value int) *%[1]sSearchOptions {
				b.b.opts.Offset = value
				return b
			}

			// %[1]sSearchIterator can access to search result.
			type %[1]sSearchIterator struct {
				b    *%[1]sSearchBuilder
				iter *search.Iterator
			}
			// Next returns next document from iter.
			func (b *%[1]sSearchIterator) Next(c context.Context) (string, *%[1]sSearch, error) {
				var s *%[1]sSearch
				if b.b.opts == nil || b.b.opts.IDsOnly != true {
					s = &%[1]sSearch{}
				}

				docID, err := b.iter.Next(s)
				if err != nil {
					return "", nil, err
				}
							`, st.Name(), "%")
	if st.HasID() {
		g.Printf("if s != nil {\n")
		g.Printf("s.ID = docID\n")
		g.Printf("}\n")
	}
	g.Printf(`
				return docID, s, err
			}

			// Cursor returns cursor of search.
			func (b *%[1]sSearchIterator) Cursor() search.Cursor {
				return b.iter.Cursor()
			}

			// %[1]sSearchStringPropertyInfo hold property info.
			type %[1]sSearchStringPropertyInfo struct {
				Name string
				b    *%[1]sSearchBuilder
			}

			// Match add query operand.
			func (p *%[1]sSearchStringPropertyInfo) Match(value string) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Match, Value: value})
				return p.b
			}

			// Asc add query operand.
			func (p *%[1]sSearchStringPropertyInfo) Asc() *%[1]sSearchBuilder {
				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
			}

			// Desc add query operand.
			func (p *%[1]sSearchStringPropertyInfo) Desc() *%[1]sSearchBuilder {
				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
			}

			// %[1]sSearchNgramStringPropertyInfo hold property info.
			type %[1]sSearchNgramStringPropertyInfo struct {
				%[1]sSearchStringPropertyInfo
			}

			// NgramMatch add query operand.
			func (p *%[1]sSearchNgramStringPropertyInfo) NgramMatch(value string) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.NgramMatch, Value: value})
				return p.b
			}

			// %[1]sSearchNumberPropertyInfo hold property info.
			type %[1]sSearchNumberPropertyInfo struct {
				Name string
				b    *%[1]sSearchBuilder
			}

			// IntGreaterThanOrEqual add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) IntGreaterThanOrEqual(value int) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value})
				return p.b
			}

			// IntGreaterThan add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) IntGreaterThan(value int) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value})
				return p.b
			}

			// IntLessThanOrEqual add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) IntLessThanOrEqual(value int) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value})
				return p.b
			}

			// IntLessThan add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) IntLessThan(value int) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value})
				return p.b
			}

			// IntEqual add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) IntEqual(value int) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value})
				return p.b
			}

			// Int64GreaterThanOrEqual add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Int64GreaterThanOrEqual(value int64) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value})
				return p.b
			}

			// Int64GreaterThan add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Int64GreaterThan(value int64) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value})
				return p.b
			}

			// Int64LessThanOrEqual add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Int64LessThanOrEqual(value int64) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value})
				return p.b
			}

			// Int64LessThan add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Int64LessThan(value int64) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value})
				return p.b
			}

			// Int64Equal add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Int64Equal(value int64) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value})
				return p.b
			}

			// Asc add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Asc() *%[1]sSearchBuilder {
				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
			}

			// Desc add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Desc() *%[1]sSearchBuilder {
				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
			}

			// %[1]sSearchBoolPropertyInfo hold property info.
			type %[1]sSearchBoolPropertyInfo struct {
				Name string
				b    *%[1]sSearchBuilder
			}

			// Equal add query operand.
			func (p *%[1]sSearchNumberPropertyInfo) Equal(value bool) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value})
				return p.b
			}

			// %[1]sSearchTimePropertyInfo hold property info.
			type %[1]sSearchTimePropertyInfo struct {
				Name string
				b    *%[1]sSearchBuilder
			}

			// query spec for time.Time.
			// https://cloud.google.com/appengine/docs/go/search/query_strings#Go_Queries_on_date_fields
			// It using date, not datetime.

			// GreaterThanOrEqual add query operand.
			func (p *%[1]sSearchTimePropertyInfo) GreaterThanOrEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value.UTC()})
				return p.b
			}

			// GreaterThan add query operand.
			func (p *%[1]sSearchTimePropertyInfo) GreaterThan(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value.UTC()})
				return p.b
			}

			// LessThanOrEqual add query operand.
			func (p *%[1]sSearchTimePropertyInfo) LessThanOrEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value.UTC()})
				return p.b
			}

			// LessThan add query operand.
			func (p *%[1]sSearchTimePropertyInfo) LessThan(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value.UTC()})
				return p.b
			}

			// Equal add query operand.
			func (p *%[1]sSearchTimePropertyInfo) Equal(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value.UTC()})
				return p.b
			}

			// Asc add query operand.
			func (p *%[1]sSearchTimePropertyInfo) Asc() *%[1]sSearchBuilder {
				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
			}

			// Desc add query operand.
			func (p *%[1]sSearchTimePropertyInfo) Desc() *%[1]sSearchBuilder {
				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
			}

			// %[1]sSearchUnixTimePropertyInfo hold property info.
			type %[1]sSearchUnixTimePropertyInfo struct {
				Name string
				b    *%[1]sSearchBuilder
			}

			// GreaterThanOrEqual add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) GreaterThanOrEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.GtEq, Value: value.UTC()})
				return p.b
			}

			// GreaterThan add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) GreaterThan(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Gt, Value: value.UTC()})
				return p.b
			}

			// LessThanOrEqual add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) LessThanOrEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.LtEq, Value: value.UTC()})
				return p.b
			}

			// LessThan add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) LessThan(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Lt, Value: value.UTC()})
				return p.b
			}

			// Equal add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) Equal(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name, Type: smgutils.Eq, Value: value.UTC()})
				return p.b
			}

			// Asc add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) Asc() *%[1]sSearchBuilder {
				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
			}

			// Desc add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) Desc() *%[1]sSearchBuilder {
				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
			}

			// UnixTimeGreaterThanOrEqual add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeGreaterThanOrEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name + "UnixTime", Type: smgutils.GtEq, Value: smgutils.Unix(value)})
				return p.b
			}

			// UnixTimeGreaterThan add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeGreaterThan(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name + "UnixTime", Type: smgutils.Gt, Value: smgutils.Unix(value)})
				return p.b
			}

			// UnixTimeLessThanOrEqual add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeLessThanOrEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name + "UnixTime", Type: smgutils.LtEq, Value: smgutils.Unix(value)})
				return p.b
			}

			// UnixTimeLessThan add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeLessThan(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name + "UnixTime", Type: smgutils.Lt, Value: smgutils.Unix(value)})
				return p.b
			}

			// UnixTimeEqual add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeEqual(value time.Time) *%[1]sSearchBuilder {
				p.b.currentOp.Children = append(p.b.currentOp.Children, &smgutils.Op{FieldName: p.Name + "UnixTime", Type: smgutils.Eq, Value: smgutils.Unix(value)})
				return p.b
			}

			// UnixTimeAsc add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeAsc() *%[1]sSearchBuilder {
				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 + "UnixTime",
					Reverse: true,
				})

				return p.b
			}

			// UnixTimeDesc add query operand.
			func (p *%[1]sSearchUnixTimePropertyInfo) UnixTimeDesc() *%[1]sSearchBuilder {
				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 + "UnixTime",
					Reverse: false,
				})

				return p.b
			}
		`, st.Name(), "%")

	g.Printf("\n\n")

	return nil
}