func jobTags(w http.ResponseWriter, r *http.Request) { query := bleve.NewMatchAllQuery() searchRequest := bleve.NewSearchRequest(query) searchRequest.Fields = []string{"tags"} tagsFacet := bleve.NewFacetRequest("tags", 99999) searchRequest.AddFacet("tags", tagsFacet) jobsSearchResults, err := doRequest("jobs", searchRequest) if err != nil { respond.With(w, r, http.StatusInternalServerError, err) return } tags := []string{} for _, t := range jobsSearchResults.Facets["tags"].Terms { tags = append(tags, fmt.Sprintf("%s", t.Term)) } respond.With(w, r, http.StatusOK, struct { Total int `json:"total"` Tags []string `json:"tags"` }{ Total: len(tags), Tags: tags, }) }
// START OMIT func main() { index, err := bleve.Open("gophercon.bleve") if err != nil { log.Fatal(err) } q := bleve.NewMatchAllQuery() req := bleve.NewSearchRequest(q) req.Size = 0 req.AddFacet("sections", // HL bleve.NewFacetRequest("section", 50)) // HL res, err := index.Search(req) if err != nil { log.Fatal(err) } fmt.Println(res) }
func resultsHandler(w http.ResponseWriter, r *http.Request) { var ( pageHTML = "results-search.html" pageInclude = "results-search.include" ) urlQuery := r.URL.Query() err := r.ParseForm() if err != nil { responseLogger(r, http.StatusBadRequest, err) w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("error in POST: %s", err))) return } // Collect the submissions fields. submission := make(map[string]interface{}) // Basic Search results if r.Method == "GET" { for k, v := range urlQuery { if k == "all_ids" { if b, err := strconv.ParseBool(strings.Join(v, "")); err == nil { submission[k] = b } } else if k == "from" || k == "size" || k == "total" { if i, err := strconv.Atoi(strings.Join(v, "")); err == nil { submission[k] = i } } else if k == "q" || k == "q_exact" || k == "q_excluded" || k == "q_required" { submission[k] = strings.Join(v, "") } } } // Advanced Search results if r.Method == "POST" { for k, v := range r.Form { if k == "all_ids" { if b, err := strconv.ParseBool(strings.Join(v, "")); err == nil { submission[k] = b } } else if k == "from" || k == "size" || k == "total" { if i, err := strconv.Atoi(strings.Join(v, "")); err == nil { submission[k] = i } } else if k == "q" || k == "q_exact" || k == "q_excluded" || k == "q_required" { submission[k] = strings.Join(v, "") } } } q, err := mapToSearchQuery(submission) if err != nil { responseLogger(r, http.StatusBadRequest, err) w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("%s", err))) return } // // Note: Add logic to handle basic and advanced search... // // q NewQueryStringQuery // q_required NewQueryStringQuery with a + prefix for each strings.Fields(q_required) value // q_exact NewMatchPhraseQuery // q_excluded NewQueryStringQuery with a - prefix for each strings.Feilds(q_excluded) value // var conQry []bleve.Query if q.Q != "" { conQry = append(conQry, bleve.NewQueryStringQuery(q.Q)) } if q.QExact != "" { conQry = append(conQry, bleve.NewMatchPhraseQuery(q.QExact)) } var terms []string for _, s := range strings.Fields(q.QRequired) { terms = append(terms, fmt.Sprintf("+%s", strings.TrimSpace(s))) } for _, s := range strings.Fields(q.QExcluded) { terms = append(terms, fmt.Sprintf("-%s", strings.TrimSpace(s))) } if len(terms) > 0 { qString := strings.Join(terms, " ") conQry = append(conQry, bleve.NewQueryStringQuery(qString)) } qry := bleve.NewConjunctionQuery(conQry) if q.Size == 0 { q.Size = 10 } searchRequest := bleve.NewSearchRequestOptions(qry, q.Size, q.From, q.Explain) if searchRequest == nil { responseLogger(r, http.StatusBadRequest, fmt.Errorf("Can't build new search request options %+v, %s", qry, err)) w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("%s", err))) return } searchRequest.Highlight = bleve.NewHighlight() searchRequest.Highlight.AddField("title") searchRequest.Highlight.AddField("content_description") searchRequest.Highlight.AddField("subjects") searchRequest.Highlight.AddField("subjects_function") searchRequest.Highlight.AddField("subjects_topical") searchRequest.Highlight.AddField("extents") subjectFacet := bleve.NewFacetRequest("subjects", 3) searchRequest.AddFacet("subjects", subjectFacet) subjectTopicalFacet := bleve.NewFacetRequest("subjects_topical", 3) searchRequest.AddFacet("subjects_topical", subjectTopicalFacet) subjectFunctionFacet := bleve.NewFacetRequest("subjects_function", 3) searchRequest.AddFacet("subjects_function", subjectFunctionFacet) // Return all fields searchRequest.Fields = []string{ "title", "identifier", "content_description", "content_condition", "resource_type", "access_restrictions", "access_restrictions_note", "use_restrictins", "use_restrictons_note", "dates", "date_expression", "extents", "subjects", "subjects_function", "subjects_topical", "linked_agents_creators", "linked_agents_subjects", "link_agents_sources", "digital_objects.title", "digital_objects.file_uris", "related_resources", "deaccessions", "accession_date", "created", } searchResults, err := index.Search(searchRequest) if err != nil { responseLogger(r, http.StatusInternalServerError, fmt.Errorf("Bleve results error %v, %s", qry, err)) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("%s", err))) return } // q (ciat.SearchQuery) performs double duty as both the structure for query submission as well // as carring the results to support paging and other types of navigation through // the query set. Results are a query with the bleve.SearchReults merged q.AttachSearchResults(searchResults) pageHTML = "results-search.html" pageInclude = "results-search.include" // Load my templates and setup to execute them tmpl, err := tmplfn.Assemble(tmplFuncs, path.Join(templatesDir, pageHTML), path.Join(templatesDir, pageInclude)) if err != nil { responseLogger(r, http.StatusInternalServerError, fmt.Errorf("Template Errors: %s, %s, %s\n", pageHTML, pageInclude, err)) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Template errors: %s", err))) return } // Render the page w.Header().Set("Content-Type", "text/html") var buf bytes.Buffer err = tmpl.Execute(&buf, q) //err = tmpl.Execute(w, q) if err != nil { responseLogger(r, http.StatusInternalServerError, fmt.Errorf("Can't render %s, %s/%s, %s", templatesDir, pageHTML, pageInclude, err)) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Template error")) return } //NOTE: This bit of ugliness is here because I need to allow <mark> elements and ellipis in the results fragments w.Write(bytes.Replace(bytes.Replace(bytes.Replace(buf.Bytes(), []byte("<mark>"), []byte("<mark>"), -1), []byte("</mark>"), []byte("</mark>"), -1), []byte(`…`), []byte(`…`), -1)) }