github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/google.golang.org/appengine/search/doc.go (about) 1 // Copyright 2015 Google Inc. All rights reserved. 2 // Use of this source code is governed by the Apache 2.0 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package search provides a client for App Engine's search service. 7 8 9 Basic Operations 10 11 Indexes contain documents. Each index is identified by its name: a 12 human-readable ASCII string. 13 14 Within an index, documents are associated with an ID, which is also 15 a human-readable ASCII string. A document's contents are a mapping from 16 case-sensitive field names to values. Valid types for field values are: 17 - string, 18 - search.Atom, 19 - search.HTML, 20 - time.Time (stored with millisecond precision), 21 - float64 (value between -2,147,483,647 and 2,147,483,647 inclusive), 22 - appengine.GeoPoint. 23 24 The Get and Put methods on an Index load and save a document. 25 A document's contents are typically represented by a struct pointer. 26 27 Example code: 28 29 type Doc struct { 30 Author string 31 Comment string 32 Creation time.Time 33 } 34 35 index, err := search.Open("comments") 36 if err != nil { 37 return err 38 } 39 newID, err := index.Put(ctx, "", &Doc{ 40 Author: "gopher", 41 Comment: "the truth of the matter", 42 Creation: time.Now(), 43 }) 44 if err != nil { 45 return err 46 } 47 48 A single document can be retrieved by its ID. Pass a destination struct 49 to Get to hold the resulting document. 50 51 var doc Doc 52 err := index.Get(ctx, id, &doc) 53 if err != nil { 54 return err 55 } 56 57 58 Search and Listing Documents 59 60 Indexes have two methods for retrieving multiple documents at once: Search and 61 List. 62 63 Searching an index for a query will result in an iterator. As with an iterator 64 from package datastore, pass a destination struct to Next to decode the next 65 result. Next will return Done when the iterator is exhausted. 66 67 for t := index.Search(ctx, "Comment:truth", nil); ; { 68 var doc Doc 69 id, err := t.Next(&doc) 70 if err == search.Done { 71 break 72 } 73 if err != nil { 74 return err 75 } 76 fmt.Fprintf(w, "%s -> %#v\n", id, doc) 77 } 78 79 Search takes a string query to determine which documents to return. The query 80 can be simple, such as a single word to match, or complex. The query 81 language is described at 82 https://cloud.google.com/appengine/docs/go/search/query_strings 83 84 Search also takes an optional SearchOptions struct which gives much more 85 control over how results are calculated and returned. 86 87 Call List to iterate over all documents in an index. 88 89 for t := index.List(ctx, nil); ; { 90 var doc Doc 91 id, err := t.Next(&doc) 92 if err == search.Done { 93 break 94 } 95 if err != nil { 96 return err 97 } 98 fmt.Fprintf(w, "%s -> %#v\n", id, doc) 99 } 100 101 102 Fields and Facets 103 104 A document's contents can be represented by a variety of types. These are 105 typically struct pointers, but they can also be represented by any type 106 implementing the FieldLoadSaver interface. The FieldLoadSaver allows metadata 107 to be set for the document with the DocumentMetadata type. Struct pointers are 108 more strongly typed and are easier to use; FieldLoadSavers are more flexible. 109 110 A document's contents can be expressed in two ways: fields and facets. 111 112 Fields are the most common way of providing content for documents. Fields can 113 store data in multiple types and can be matched in searches using query 114 strings. 115 116 Facets provide a way to attach categorical information to a document. The only 117 valid types for facets are search.Atom and float64. Facets allow search 118 results to contain summaries of the categories matched in a search, and to 119 restrict searches to only match against specific categories. 120 121 By default, for struct pointers, all of the struct fields are used as document 122 fields, and the field name used is the same as on the struct (and hence must 123 start with an upper case letter). Struct fields may have a 124 `search:"name,options"` tag. The name must start with a letter and be 125 composed only of word characters. If options is "facet" then the struct 126 field will be used as a document facet. If options is "" then the comma 127 may be omitted. There are no other recognized options. 128 129 Example code: 130 131 // A and B are renamed to a and b. 132 // A, C and I are facets. 133 // D's tag is equivalent to having no tag at all (E). 134 // I has tag information for both the search and json packages. 135 type TaggedStruct struct { 136 A float64 `search:"a,facet"` 137 B float64 `search:"b"` 138 C float64 `search:",facet"` 139 D float64 `search:""` 140 E float64 141 I float64 `search:",facet" json:"i"` 142 } 143 144 145 The FieldLoadSaver Interface 146 147 A document's contents can also be represented by any type that implements the 148 FieldLoadSaver interface. This type may be a struct pointer, but it 149 does not have to be. The search package will call Load when loading the 150 document's contents, and Save when saving them. In addition to a slice of 151 Fields, the Load and Save methods also use the DocumentMetadata type to 152 provide additional information about a document (such as its Rank, or set of 153 Facets). Possible uses for this interface include deriving non-stored fields, 154 verifying fields or setting specific languages for string and HTML fields. 155 156 Example code: 157 158 type CustomFieldsExample struct { 159 // Item's title and which language it is in. 160 Title string 161 Lang string 162 // Mass, in grams. 163 Mass int 164 } 165 166 func (x *CustomFieldsExample) Load(fields []search.Field, meta *search.DocumentMetadata) error { 167 // Load the title field, failing if any other field is found. 168 for _, f := range fields { 169 if f.Name != "title" { 170 return fmt.Errorf("unknown field %q", f.Name) 171 } 172 s, ok := f.Value.(string) 173 if !ok { 174 return fmt.Errorf("unsupported type %T for field %q", f.Value, f.Name) 175 } 176 x.Title = s 177 x.Lang = f.Language 178 } 179 // Load the mass facet, failing if any other facet is found. 180 for _, f := range meta.Facets { 181 if f.Name != "mass" { 182 return fmt.Errorf("unknown facet %q", f.Name) 183 } 184 m, ok := f.Value.(float64) 185 if !ok { 186 return fmt.Errorf("unsupported type %T for facet %q", f.Value, f.Name) 187 } 188 x.Mass = int(m) 189 } 190 return nil 191 } 192 193 func (x *CustomFieldsExample) Save() ([]search.Field, *search.DocumentMetadata, error) { 194 fields := []search.Field{ 195 {Name: "title", Value: x.Title, Language: x.Lang}, 196 } 197 meta := &search.DocumentMetadata{ 198 Facets: { 199 {Name: "mass", Value: float64(x.Mass)}, 200 }, 201 } 202 return fields, meta, nil 203 } 204 */ 205 package search