Example #1
0
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
}
Example #4
0
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
}