func (t *Task) Save() ([]search.Field, *search.DocumentMetadata, error) { isArchived := search.Atom("false") if t.IsArchived { isArchived = search.Atom("true") } return []search.Field{ {Name: "CreatedAt", Value: t.CreatedAt}, {Name: "Title", Value: t.Title}, {Name: "Description", Value: t.Description}, {Name: "IsArchived", Value: isArchived}, {Name: "SpaceID", Value: search.Atom(t.SpaceID)}, }, nil, nil }
func indexIdiomCheatsheets(c context.Context, idiom *Idiom) error { index, err := gaesearch.Open("cheatsheets") if err != nil { return err } // Index each impl individually. for _, impl := range idiom.Implementations { docID := fmt.Sprintf("%d_%d", idiom.Id, impl.Id) doc := &cheatSheetLineDoc{ Lang: gaesearch.Atom(impl.LanguageName), IdiomID: gaesearch.Atom(strconv.Itoa(idiom.Id)), IdiomTitle: gaesearch.Atom(idiom.Title), IdiomLeadParagraph: gaesearch.Atom(idiom.LeadParagraph), ImplID: gaesearch.Atom(strconv.Itoa(impl.Id)), ImplImportsBlock: gaesearch.Atom(impl.ImportsBlock), ImplCodeBlock: gaesearch.Atom(impl.CodeBlock), ImplCodeBlockComment: gaesearch.Atom(impl.AuthorComment), } // Weird that the search API doesn't have batch queries. // TODO: index each impl concurrently? _, err = index.Put(c, docID, doc) if err != nil { return err } } return nil }
func indexIdiomFullText(c context.Context, idiom *Idiom, idiomKey *datastore.Key) error { index, err := gaesearch.Open("idioms") if err != nil { return err } // By using directly the idiom Key as docID, // we can leverage faster ID-only search later. docID := strconv.Itoa(idiom.Id) w, wTitle, wLead := idiom.ExtractIndexableWords() doc := &searchableIdiomDoc{ IdiomKeyString: gaesearch.Atom(idiomKey.Encode()), IdiomID: gaesearch.Atom(strconv.Itoa(idiom.Id)), Bulk: strings.Join(w, " "), Langs: implementedLanguagesConcat(idiom), TitleWords: strings.Join(wTitle, " "), LeadWords: strings.Join(wLead, " "), } doc.TitleOrLeadWords = doc.TitleWords + " " + doc.LeadWords _, err = index.Put(c, docID, doc) if err != nil { return err } // Also index each impl individually, // so we know what to highlight. indexImpl, err := gaesearch.Open("impls") if err != nil { return err } for _, impl := range idiom.Implementations { implDocID := fmt.Sprintf("%d_%d", idiom.Id, impl.Id) w := impl.ExtractIndexableWords() implDoc := &searchableImplDoc{ Lang: impl.LanguageName, IdiomID: gaesearch.Atom(strconv.Itoa(idiom.Id)), Bulk: strings.Join(w, " "), } // Weird that the search API doesn't have batch queries. // TODO: index each impl concurrently? // TODO: index only last edited impl? _, err = indexImpl.Put(c, implDocID, implDoc) if err != nil { return err } } return nil }
func (p *Package) Save() ([]search.Field, *search.DocumentMetadata, error) { fields := []search.Field{ {Name: "Name", Value: search.Atom(p.Name)}, {Name: "Path", Value: p.Path}, {Name: "Synopsis", Value: p.Synopsis}, {Name: "Score", Value: p.Score}, {Name: "ImportCount", Value: float64(p.ImportCount)}, {Name: "Stars", Value: float64(p.Stars)}, } fork := fmt.Sprint(p.Fork) // "true" or "false" meta := &search.DocumentMetadata{ // Customize the rank property by the product of the package score and // natural logarithm of the import count. Rank must be a positive integer. // Use 1 as minimum rank and keep 3 digits of precision to distinguish // close ranks. Rank: int(math.Max(1, 1000*p.Score*math.Log(math.E+float64(p.ImportCount)))), Facets: []search.Facet{ {Name: "Fork", Value: search.Atom(fork)}, }, } return fields, meta, nil }