google.golang.org/appengine/search 包 (v1.6.8)

软件包搜索为 App Engine 的搜索服务提供客户端。

基本运算

索引包含文档。每个索引均使用名称(即直观易懂的 ASCII 字符串)标识。

在索引中,文档与 ID 相关联,ID 也是直观易懂的 ASCII 字符串。文档的内容是从区分大小写的字段名称到值的映射。字段值的有效类型有:

  • string,
  • search.Atom,
  • search.HTML,
  • time.Time(以毫秒级精度存储),
  • float64(介于 -2,147,483,647 和 2,147,483,647 之间的浮点值,含边界值),
  • appengine.GeoPoint。

索引上的 Get 和 Put 方法会加载并保存文档。文档的内容通常用结构体指针表示。

示例代码:

type Doc struct {
    Author   string
    Comment  string
    Creation time.Time
}

index, err := search.Open("comments")
if err != nil {
    return err
}
newID, err := index.Put(ctx, "", &Doc{
    Author:   "gopher",
    Comment:  "the truth of the matter",
    Creation: time.Now(),
})
if err != nil {
    return err
}

单个文档可以通过其 ID 进行检索。将目标结构体传递给 Get 以保存生成的文档。

var doc Doc
err := index.Get(ctx, id, &doc)
if err != nil {
    return err
}

搜索和列出文档

索引有两种方法可以同时检索多个文档:Search 和 List。

搜索查询索引将生成迭代器。与软件包数据存储区中的迭代器一样,将目标结构体传递给 Next 以解码下一个结果。当迭代器结束时,Next 将返回 Done。

for t := index.Search(ctx, "Comment:truth", nil); ; {
    var doc Doc
    id, err := t.Next(&doc)
    if err == search.Done {
        break
    }
    if err != nil {
        return err
    }
    fmt.Fprintf(w, "%s -> %#v\n", id, doc)
}

Search 采用字符串查询来确定要返回的文档。查询可以很简单(例如要匹配的单个词),也可以很复杂。https://cloud.google.com/appengine/docs/standard/go/search/query_strings 中介绍了查询语言

Search 还采用可选的 SearchOptions 结构体,该结构体可以更好地控制结果的计算和返回方式。

调用 List 遍历索引中的所有文档。

for t := index.List(ctx, nil); ; {
    var doc Doc
    id, err := t.Next(&doc)
    if err == search.Done {
        break
    }
    if err != nil {
        return err
    }
    fmt.Fprintf(w, "%s -> %#v\n", id, doc)
}

字段和构面

文档的内容可以用各种类型表示。这些通常是结构体指针,但它们也可以用实现 FieldLoadSaver 接口的任何类型表示。FieldLoadSaver 允许为 DocumentMetadata 类型的文档设置元数据。结构体指针的类型更强,更易于使用;FieldLoadSavers 更灵活。

文档的内容可以用两种方式表示:字段和构面。

字段是提供文档内容最常见的方式。字段可以存储多种类型的数据,并且可以使用查询字符串在搜索中进行匹配。

通过构面,您可以将分类信息附加到文档。唯一有效的构面类型是 search.Atom 和 float64。构面允许搜索结果包含搜索中匹配类别的摘要,并将搜索限制为仅匹配特定类别。

默认情况下,对于结构体指针,所有结构体字段都用作文档字段,使用的字段名称与结构体上的相同(因此必须以大写字母开头)。结构体字段可能具有 search:"name,options" 标记。名称必须以字母开头,并且仅由单词字符组成。“-”标记名称表示该字段将被忽略。如果选项为“facet”,则结构体字段将用作文档构面。如果选项为 "",则可以省略英文逗号。没有其他识别的选项。

示例代码:

// A and B are renamed to a and b.
// A, C and I are facets.
// D's tag is equivalent to having no tag at all (E).
// F and G are ignored entirely by the search package.
// I has tag information for both the search and json packages.
type TaggedStruct struct {
    A float64 `search:"a,facet"`
    B float64 `search:"b"`
    C float64 `search:",facet"`
    D float64 `search:""`
    E float64
    F float64 `search:"-"`
    G float64 `search:"-,facet"`
    I float64 `search:",facet" json:"i"`
}

FieldLoadSaver 接口

文档的内容也可以用实现 FieldLoadSaver 接口的任何类型表示。此类型可以是但并非必须是结构体指针。搜索软件包将在加载文档内容时调用 Load,并在保存时调用 Save。除了 Field 的切片之外,Load 和 Save 方法还使用 DocumentMetadata 类型提供有关文档的其他信息(例如其 Rank 或 Facet 集)。此接口的可能用途包括派生非存储字段、验证字段或为字符串和 HTML 字段设置特定语言。

示例代码:

type CustomFieldsExample struct {
    // Item's title and which language it is in.
    Title string
    Lang  string
    // Mass, in grams.
    Mass int
}

func (x *CustomFieldsExample) Load(fields []search.Field, meta *search.DocumentMetadata) error {
    // Load the title field, failing if any other field is found.
    for _, f := range fields {
        if f.Name != "title" {
            return fmt.Errorf("unknown field %q", f.Name)
        }
        s, ok := f.Value.(string)
        if !ok {
            return fmt.Errorf("unsupported type %T for field %q", f.Value, f.Name)
        }
        x.Title = s
        x.Lang = f.Language
    }
    // Load the mass facet, failing if any other facet is found.
    for _, f := range meta.Facets {
        if f.Name != "mass" {
            return fmt.Errorf("unknown facet %q", f.Name)
        }
        m, ok := f.Value.(float64)
        if !ok {
            return fmt.Errorf("unsupported type %T for facet %q", f.Value, f.Name)
        }
        x.Mass = int(m)
    }
    return nil
}

func (x *CustomFieldsExample) Save() ([]search.Field, *search.DocumentMetadata, error) {
    fields := []search.Field{
        {Name: "title", Value: x.Title, Language: x.Lang},
    }
    meta := &search.DocumentMetadata{
        Facets: {
            {Name: "mass", Value: float64(x.Mass)},
        },
    }
    return fields, meta, nil
}

变量

ErrInvalidDocumentType、ErrNoSuchDocument、ErrTooManyDocuments

var (
	// ErrInvalidDocumentType is returned when methods like Put, Get or Next
	// are passed a dst or src argument of invalid type.
	ErrInvalidDocumentType = errors.New("search: invalid document type")

	// ErrNoSuchDocument is returned when no document was found for a given ID.
	ErrNoSuchDocument = errors.New("search: no such document")

	// ErrTooManyDocuments is returned when the user passes too many documents to
	// PutMulti or DeleteMulti.
	ErrTooManyDocuments = fmt.Errorf("search: too many documents given to put or delete (max is %d)", maxDocumentsPerPutDelete)
)

完成

var Done = errors.New("search: query has no more results")

查询迭代完成时将返回 Done。

函数

func LoadStruct

func LoadStruct(dst interface{}, f []Field) error

LoadStruct 加载从 f 到 dst 的字段。dst 必须是结构体指针。

Atom

type Atom string

Atom 是一个文档字段,其内容以单个不可分割的字符串的形式编入索引。

Cursor

type Cursor string

Cursor 表示迭代器的位置。

游标的字符串值在网络上是安全的。它可以保存起来,在恢复后可供日后使用。

DocumentMetadata

type DocumentMetadata struct {
	// Rank is an integer specifying the order the document will be returned in
	// search results. If zero, the rank will be set to the number of seconds since
	// 2011-01-01 00:00:00 UTC when being Put into an index.
	Rank int
	// Facets is the set of facets for this document.
	Facets []Facet
}

DocumentMetadata 是一个包含给定文档的描述信息的结构体。

ErrFacetMismatch

type ErrFacetMismatch struct {
	StructType reflect.Type
	FacetName  string
	Reason     string
}

将构面加载到与其先前存储类型不同的类型时,或者在目标结构体中缺少或未导出字段时,系统将返回 ErrFacetMismatch。StructType 是传递给 Iterator.Next 的目标参数指向的结构体类型。

func (*ErrFacetMismatch) Error

func (e *ErrFacetMismatch) Error() string

ErrFieldMismatch

type ErrFieldMismatch struct {
	FieldName string
	Reason    string
}

将字段加载到与其先前存储类型不同的类型时,或者在目标结构体中缺少或未导出字段时,系统将返回 ErrFieldMismatch。

func (*ErrFieldMismatch) Error

func (e *ErrFieldMismatch) Error() string

Facet

type Facet struct {
	// Name is the facet name. A valid facet name matches /[A-Za-z][A-Za-z0-9_]*/.
	// A facet name cannot be longer than 500 characters.
	Name string
	// Value is the facet value.
	//
	// When being used in documents (for example, in
	// DocumentMetadata.Facets), the valid types are:
	//  - search.Atom,
	//  - float64.
	//
	// When being used in SearchOptions.Refinements or being returned
	// in FacetResult, the valid types are:
	//  - search.Atom,
	//  - search.Range.
	Value interface{}
}

Facet 是一个名称/值对,用于向文档添加分类信息。

FacetResult

type FacetResult struct {
	Facet

	// Count is the number of times this specific facet and value appeared in the
	// matching documents.
	Count int
}

FacetResult 表示在与搜索请求匹配的文档中,特定构面和值出现的次数。

FacetSearchOption

type FacetSearchOption interface {
	// contains filtered or unexported methods
}

FacetSearchOption 控制搜索结果中返回的构面信息。

func AutoFacetDiscovery

func AutoFacetDiscovery(facetLimit, valueLimit int) FacetSearchOption

AutoFacetDiscovery 会返回 FacetSearchOption,用于为搜索启用自动构面发现。自动构面发现用于查找匹配文档汇总中最常出现的构面。

返回的最大构面数由 facetLimit 控制,每个构面的最大值也由 facetLimit 控制。限值为零表示应使用默认限值。

func FacetDiscovery

func FacetDiscovery(name string, value ...interface{}) FacetSearchOption

FacetDiscovery 会返回 FacetSearchOption,用于选择将与搜索结果一起返回的构面。默认情况下,系统将返回该构面最常出现的值。但是,您还可以指定要返回的特定 Atom 或特定 Range 的列表。

func FacetDocumentDepth

func FacetDocumentDepth(depth int) FacetSearchOption

FacetDocumentDepth 会返回 FacetSearchOption,用于通过正在准备的构面结果控制要计算的文档数。

Field

type Field struct {
	// Name is the field name. A valid field name matches /[A-Za-z][A-Za-z0-9_]*/.
	Name string
	// Value is the field value. The valid types are:
	//  - string,
	//  - search.Atom,
	//  - search.HTML,
	//  - time.Time (stored with millisecond precision),
	//  - float64,
	//  - GeoPoint.
	Value interface{}
	// Language is a two-letter ISO 639-1 code for the field's language,
	// defaulting to "en" if nothing is specified. It may only be specified for
	// fields of type string and search.HTML.
	Language string
	// Derived marks fields that were calculated as a result of a
	// FieldExpression provided to Search. This field is ignored when saving a
	// document.
	Derived bool
}

Field 是名称/值对。可以加载搜索索引的文档并将其另存为一系列 Field。

func SaveStruct

func SaveStruct(src interface{}) ([]Field, error)

SaveStruct 会将 src 中的字段以 Field 切片形式返回。src 必须是结构体指针。

FieldExpression

type FieldExpression struct {
	// Name is the name to use for the computed field.
	Name string

	// Expr is evaluated to provide a custom content snippet for each document.
	// See https://cloud.google.com/appengine/docs/standard/go/search/options for
	// the supported expression syntax.
	Expr string
}

FieldExpression 定义要为每个结果求值的自定义表达式。

FieldList

type FieldList []Field

FieldList 会转换 []Field 以实现 FieldLoadSaver。

func (*FieldList) Load

func (l *FieldList) Load(f []Field, _ *DocumentMetadata) error

Load 会将所有提供的构面加载到 l 中,而不会先将 *l 重置为空切片。

func (*FieldList) Save

func (l *FieldList) Save() ([]Field, *DocumentMetadata, error)

Save 会将 l 的所有字段以 Field 切片的形式返回。

FieldLoadSaver

type FieldLoadSaver interface {
	Load([]Field, *DocumentMetadata) error
	Save() ([]Field, *DocumentMetadata, error)
}

FieldLoadSaver 可以与包含其他文档元数据的 Field 切片相互转换。

HTML

type HTML string

HTML 是一个文档字段,其内容以 HTML 的形式编入索引。仅文本节点编入索引:“foobar”将被视为“foobar”。

Index

type Index struct {
	// contains filtered or unexported fields
}

Index 是文档的索引。

func Open

func Open(name string) (*Index, error)

Open 会打开具有给定名称的索引。如果索引尚不存在,则创建索引。

名称是直观易懂的 ASCII 字符串。它不能包含空白字符,不能以“!”开头。

func (*Index) Delete

func (x *Index) Delete(c context.Context, id string) error

Delete 会从索引中删除文档。

func (*Index) DeleteMulti

func (x *Index) DeleteMulti(c context.Context, ids []string) error

DeleteMulti 会从索引中删除多个文档。

返回的错误可能是 appengine.MultiError 实例,在这种情况下,其大小与 src 相同,并且其中的每个错误都将与 src 中的项相对应。

func (*Index) Get

func (x *Index) Get(c context.Context, id string, dst interface{}) error

Get 会将具有给定 ID 的文档加载到 dst 中。

ID 是直观易懂的 ASCII 字符串。它必须为非空,不得包含空白字符,且不能以“!”开头。

dst 必须是非 nil 结构体指针或实现 FieldLoadSaver 接口。

将字段加载到与其先前存储类型不同的类型时,或者在目标结构体中缺少或未导出字段时,系统将返回 ErrFieldMismatch。只有在 dst 是结构体指针时,系统才会返回 ErrFieldMismatch。由被调用者决定此错误是严重错误、可恢复错误还是可忽略错误。

func (*Index) List

func (x *Index) List(c context.Context, opts *ListOptions) *Iterator

List 会列出索引中的所有文档。文档以递增的 ID 顺序返回。

func (*Index) Put

func (x *Index) Put(c context.Context, id string, src interface{}) (string, error)

Put 会将 src 保存到索引中。如果 ID 为空,则服务会分配新 ID 并返回。如果 ID 不为空,则替换该 ID 的任何现有索引条目。

ID 是直观易懂的 ASCII 字符串。它不能包含空白字符,不能以“!”开头。

src 必须是非 nil 结构体指针或实现 FieldLoadSaver 接口。

func (*Index) PutMulti

func (x *Index) PutMulti(c context.Context, ids []string, srcs []interface{}) ([]string, error)

PutMulti 与 Put 类似,但用于一次将多个文档添加到索引中时效率更高。

一次最多可以添加 200 个文档。如果您尝试添加更多文档,则会返回 ErrTooManyDocuments。

ID 可以是空切片(这意味着将为每个添加的文档分配新 ID),或者是与 src 大小相同的切片。

错误可能是 appengine.MultiError 实例,在这种情况下,其大小与 src 相同,并且其中的每个错误都将与 src 中的项相对应。

func (x *Index) Search(c context.Context, query string, opts *SearchOptions) *Iterator

Search 会搜索给定查询的索引。

Iterator

type Iterator struct {
	// contains filtered or unexported fields
}

Iterator 是搜索查询索引或列出索引的结果。

func (*Iterator) Count

func (t *Iterator) Count() int

Count 会返回查询匹配的文档数的近似值。只有调用 Search 返回的迭代器才有效。

func (*Iterator) Cursor

func (t *Iterator) Cursor() Cursor

Cursor 返回与当前文档关联的游标(即最近通过调用 Next 返回的文档)。

在将来调用 Search 时传递此游标将导致这些结果从当前文档之后的第一个文档开始。

func (*Iterator) Facets

func (t *Iterator) Facets() ([][]FacetResult, error)

如果在 SearchOptions 中请求了任何构面,Facets 将返回搜索结果中找到的构面。

func (*Iterator) Next

func (t *Iterator) Next(dst interface{}) (string, error)

Next 会返回下一个结果的 ID。如果没有更多结果,Next 会将 Done 作为错误返回。

dst 必须是非 nil 结构体指针,实现 FieldLoadSaver 接口,或者是 nil 接口值。如果提供了非 nil 的 dst,则将填充已编入索引的字段。如果使用 IDsOnly 选项创建此迭代器,则忽略 dst。

ListOptions

type ListOptions struct {
	// StartID is the inclusive lower bound for the ID of the returned
	// documents. The zero value means all documents will be returned.
	StartID string

	// Limit is the maximum number of documents to return. The zero value
	// indicates no limit.
	Limit int

	// IDsOnly indicates that only document IDs should be returned for the list
	// operation; no document fields are populated.
	IDsOnly bool
}

ListOptions 是用于列出索引中的文档的选项。传递 nil*ListOptions 等同于使用默认值。

Range

type Range struct {
	Start, End float64
}

Range 表示包含开始值和不包含结束值的数值范围。 Start 可以指定为 math.Inf(-1),表示没有最小值,End 同样可以指定为 math.Inf(1);Start 或 End 这两者中至少有一个必须是有限大数值。

func AtLeast

func AtLeast(min float64) Range

AtLeast 会返回与任何大于或等于最小值的值匹配的 Range。

func LessThan

func LessThan(max float64) Range

LessThan 会返回与任何小于最大值的值匹配的 Range。

Scorer

type Scorer interface {
	// contains filtered or unexported methods
}

Scorer 定义文档的评分方式。

MatchScorer、RescoringMatchScorer

var (
	// MatchScorer assigns a score based on term frequency in a document.
	MatchScorer Scorer = enumScorer{pb.ScorerSpec_MATCH_SCORER}

	// RescoringMatchScorer assigns a score based on the quality of the query
	// match. It is similar to a MatchScorer but uses a more complex scoring
	// algorithm based on match term frequency and other factors like field type.
	// Please be aware that this algorithm is continually refined and can change
	// over time without notice. This means that the ordering of search results
	// that use this scorer can also change without notice.
	RescoringMatchScorer Scorer = enumScorer{pb.ScorerSpec_RESCORING_MATCH_SCORER}
)

SearchOptions

type SearchOptions struct {
	// Limit is the maximum number of documents to return. The zero value
	// indicates no limit.
	Limit int

	// IDsOnly indicates that only document IDs should be returned for the search
	// operation; no document fields are populated.
	IDsOnly bool

	// Sort controls the ordering of search results.
	Sort *SortOptions

	// Fields specifies which document fields to include in the results. If omitted,
	// all document fields are returned. No more than 100 fields may be specified.
	Fields []string

	// Expressions specifies additional computed fields to add to each returned
	// document.
	Expressions []FieldExpression

	// Facets controls what facet information is returned for these search results.
	// If no options are specified, no facet results will be returned.
	Facets []FacetSearchOption

	// Refinements filters the returned documents by requiring them to contain facets
	// with specific values. Refinements are applied in conjunction for facets with
	// different names, and in disjunction otherwise.
	Refinements []Facet

	// Cursor causes the results to commence with the first document after
	// the document associated with the cursor.
	Cursor Cursor

	// Offset specifies the number of documents to skip over before returning results.
	// When specified, Cursor must be nil.
	Offset int

	// CountAccuracy specifies the maximum result count that can be expected to
	// be accurate. If zero, the count accuracy defaults to 20.
	CountAccuracy int
}

SearchOptions 是搜索索引的选项。传递 nil*SearchOptions 等同于使用默认值。

SortExpression

type SortExpression struct {
	// Expr is evaluated to provide a sorting value for each document.
	// See https://cloud.google.com/appengine/docs/standard/go/search/options for
	// the supported expression syntax.
	Expr string

	// Reverse causes the documents to be sorted in ascending order.
	Reverse bool

	// The default value to use when no field is present or the expresion
	// cannot be calculated for a document. For text sorts, Default must
	// be of type string; for numeric sorts, float64.
	Default interface{}
}

SortExpression 定义用于对文档进行排序的单个维度。

SortOptions

type SortOptions struct {
	// Expressions is a slice of expressions representing a multi-dimensional
	// sort.
	Expressions []SortExpression

	// Scorer, when specified, will cause the documents to be scored according to
	// search term frequency.
	Scorer Scorer

	// Limit is the maximum number of objects to score and/or sort. Limit cannot
	// be more than 10,000. The zero value indicates a default limit.
	Limit int
}

SortOptions 控制搜索结果的排序和评分。