123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733 |
- package main
- import (
- "context"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "github.com/olivere/elastic/v7"
- util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
- "log"
- "sort"
- //"sort"
- "strings"
- "time"
- )
- func SearchProjectFullScoring(client *elastic.Client, target InputData, projectName, areacode, publish string) ([]map[string]interface{}, error) {
- seenIDs := make(map[string]*elastic.SearchHit)
- province, city := "", ""
- if areacode != "" {
- code := areacode[:6]
- where := map[string]interface{}{
- "code": code,
- }
- res, _ := MgoQY.FindOne("address_new_2020", where)
- province = util.ObjToString((*res)["province"])
- city = util.ObjToString((*res)["city"])
- }
- // 1. 精准查询(权重 1.0)
- preciseHits, err := searchPrecise(client, projectName, province, city, publish, 20)
- if err != nil {
- return nil, err
- }
- for _, hit := range preciseHits {
- if _, exists := seenIDs[hit.Id]; !exists {
- seenIDs[hit.Id] = hit
- }
- }
- // 2. 分词查询(权重 0.8)
- tokenHits, err := searchByToken(client, projectName, province, city, publish, 20)
- if err != nil {
- return nil, err
- }
- for _, hit := range tokenHits {
- if _, exists := seenIDs[hit.Id]; !exists {
- seenIDs[hit.Id] = hit
- }
- }
- // 3. common 查询(权重 0.5)
- commonHits, err := searchCommon(client, projectName, province, city, publish, 10)
- if err != nil {
- return nil, err
- }
- for _, hit := range commonHits {
- if _, exists := seenIDs[hit.Id]; !exists {
- seenIDs[hit.Id] = hit
- }
- }
- // 4. 合并 + 打分增强
- var results []map[string]interface{}
- //nameScore := computeNameScore(projectName)
- var allCandidates = []EsDocument{}
- for id, hit := range seenIDs {
- var doc map[string]interface{}
- if err := json.Unmarshal(hit.Source, &doc); err != nil {
- continue
- }
- // 从 Mongo 读取 detail 字段用于后续 buyer 过滤
- bidd, _ := MgoB.FindById("bidding", id, nil)
- detail := util.ObjToString((*bidd)["detail"])
- doc["detail"] = detail
- /**
- "id", "title", "projectname", "projectcode", "bidamount", "area", "city",
- "toptype", "subtype", "buyer", "budget", "buyerperson", "buyertel",
- "s_winner", "winnertel", "agency", "publishtime"
- */
- candidate := EsDocument{
- Id: util.ObjToString(doc["id"]),
- Title: util.ObjToString(doc["title"]),
- Projectname: util.ObjToString(doc["projectname"]),
- Toptype: util.ObjToString(doc["toptype"]),
- Subtype: util.ObjToString(doc["subtype"]),
- Area: util.ObjToString(doc["area"]),
- City: util.ObjToString(doc["city"]),
- Buyer: util.ObjToString(doc["buyer"]),
- SWinner: util.ObjToString(doc["s_winner"]),
- Bidamount: util.Float64All(doc["bidamount"]),
- Publishtime: util.Int64All(doc["publishtime"]),
- Agency: util.ObjToString(doc["agency"]),
- WinnerTel: util.ObjToString(doc["winnertel"]),
- BuyerTel: util.ObjToString(doc["buyertel"]),
- BuyerPerson: util.ObjToString(doc["buyerperson"]),
- Budget: util.Float64All(doc["budget"]),
- }
- score := calculateConfidenceScore(target, candidate)
- candidate.Score = score
- allCandidates = append(allCandidates, candidate)
- }
- // 打印打分调试
- //for i, c := range allCandidates {
- // fmt.Printf("Candidat 排序前: %d Score: %.4f\n", i, c.Score)
- //}
- // 排序(降序)
- sort.SliceStable(allCandidates, func(i, j int) bool {
- return allCandidates[i].Score > allCandidates[j].Score
- })
- //for i, c := range allCandidates {
- // fmt.Printf("Candidate 排序后: %d Score: %.4f\n", i, c.Score)
- //}
- //// 5. 排序
- //sort.Slice(allCandidates, func(i, j int) bool {
- // return allCandidates[i].Score > allCandidates[j].Score
- //})
- for _, doc := range allCandidates {
- item := map[string]interface{}{
- "id": doc.Id,
- "title": doc.Title,
- "projectname": doc.Projectname,
- "projectcode": doc.ProjectCode,
- "toptype": doc.Toptype,
- "subtype": doc.Subtype,
- "area": doc.Area,
- "city": doc.City,
- "buyer": doc.Buyer,
- "budget": doc.Budget,
- "bidamount": doc.Bidamount,
- "winner": doc.Winner,
- "detail": doc.Detail,
- "publishtime": doc.Publishtime,
- "agency": doc.Agency,
- "s_winner": doc.SWinner,
- "winnertel": doc.WinnerTel,
- "buyertel": doc.BuyerTel,
- "buyerperson": doc.BuyerPerson,
- "score": doc.Score,
- }
- results = append(results, item)
- }
- return results, nil
- }
- // searchPrecise 精准查询
- func searchPrecise22(client *elastic.Client, projectName, province, city, publish string, maxResults int) ([]*elastic.SearchHit, error) {
- fieldsToTry := []string{"projectname.pname", "title", "detail"}
- filtersToTry := [][]elastic.Query{
- {elastic.NewTermsQuery("subtype", "中标", "成交", "合同", "单一")},
- {elastic.NewTermsQuery("toptype", "招标", "预告", "采购意向")},
- {elastic.NewTermsQuery("toptype", "拟建")},
- }
- var allResults []*elastic.SearchHit
- seenIDs := make(map[string]bool)
- query := elastic.NewBoolQuery()
- for _, field := range fieldsToTry {
- if field == "detail" && len(allResults) > maxResults {
- break
- }
- for _, filter := range filtersToTry {
- //query := elastic.NewBoolQuery().
- query.Must(elastic.NewMultiMatchQuery(projectName, field).Type("phrase")).
- Filter(filter...)
- fetchFields := elastic.NewFetchSourceContext(true).Include("id", "title", "projectname", "projectcode", "bidamount", "area", "city", "toptype", "subtype", "buyer", "budget", "buyerperson", "buyertel", "s_winner", "winnertel", "agency", "publishtime")
- searchResult, err := client.Search().
- Index("bidding").
- Query(query).
- Size(maxResults).
- FetchSourceContext(fetchFields).
- Do(context.Background())
- if err != nil {
- return nil, err
- }
- for _, hit := range searchResult.Hits.Hits {
- if !seenIDs[hit.Id] {
- seenIDs[hit.Id] = true
- allResults = append(allResults, hit)
- }
- }
- }
- }
- return allResults, nil
- }
- func searchPrecise(client *elastic.Client, projectName, province, city, publish string, maxResults int) ([]*elastic.SearchHit, error) {
- fieldsToTry := []string{"projectname.pname", "title", "detail"}
- filtersToTry := [][]elastic.Query{
- {elastic.NewTermsQuery("subtype", "中标", "成交", "合同", "单一")},
- {elastic.NewTermsQuery("toptype", "招标", "预告", "采购意向")},
- {elastic.NewTermsQuery("toptype", "拟建")},
- }
- var allResults []*elastic.SearchHit
- seenIDs := make(map[string]bool)
- // 解析发布时间
- var t time.Time
- var err error
- if publish != "" {
- t, err = time.Parse("200601", publish)
- if err != nil {
- log.Println("时间解析失败:", err)
- }
- }
- for _, field := range fieldsToTry {
- var dateRangeStart, dateRangeEnd int64
- if !t.IsZero() {
- if field == "detail" {
- dateRangeStart, dateRangeEnd = getYearRange(t, 60)
- } else {
- dateRangeStart, dateRangeEnd = getYearRange(t, 36)
- }
- }
- for _, filters := range filtersToTry {
- var queries []*elastic.BoolQuery
- if field == "detail" {
- // detail 只加时间 + filter
- query := elastic.NewBoolQuery()
- query = query.Must(elastic.NewMultiMatchQuery(projectName, field).Type("phrase"))
- query = query.Filter(filters...)
- if !t.IsZero() {
- query = query.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, query)
- } else {
- // 1. 省 + 市 查询
- if province != "" && city != "" {
- query1 := elastic.NewBoolQuery()
- query1 = query1.Must(elastic.NewMultiMatchQuery(projectName, field).Type("phrase"))
- query1 = query1.Must(elastic.NewTermQuery("province", province))
- query1 = query1.Must(elastic.NewTermQuery("city", city))
- query1 = query1.Filter(filters...)
- if !t.IsZero() {
- query1 = query1.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, query1)
- }
- // 2. 仅省份(城市为空或不同)
- if province != "" {
- query2 := elastic.NewBoolQuery()
- query2 = query2.Must(elastic.NewMultiMatchQuery(projectName, field).Type("phrase"))
- query2 = query2.Must(elastic.NewTermQuery("province", province))
- query2 = query2.Filter(filters...)
- if !t.IsZero() {
- query2 = query2.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, query2)
- }
- // 3. 不限制省市
- if province != "" {
- query3 := elastic.NewBoolQuery()
- query3 = query3.Must(elastic.NewMultiMatchQuery(projectName, field).Type("phrase"))
- query3 = query3.Filter(filters...)
- if !t.IsZero() {
- query3 = query3.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, query3)
- }
- }
- for _, query := range queries {
- fetchFields := elastic.NewFetchSourceContext(true).Include(
- "id", "title", "projectname", "projectcode", "bidamount", "area", "city",
- "toptype", "subtype", "buyer", "budget", "buyerperson", "buyertel",
- "s_winner", "winnertel", "agency", "publishtime")
- searchResult, err := client.Search().
- Index("bidding").
- Query(query).
- Size(maxResults).
- FetchSourceContext(fetchFields).
- Do(context.Background())
- if err != nil {
- return nil, err
- }
- // 打印 query JSON(调试用)
- //if sourceQ, err := query.Source(); err == nil {
- // log.Println(printInterfaceAsJSON(sourceQ))
- //}
- for _, hit := range searchResult.Hits.Hits {
- if !seenIDs[hit.Id] {
- seenIDs[hit.Id] = true
- allResults = append(allResults, hit)
- }
- }
- }
- }
- // detail 的命中足够就提前结束
- if field == "detail" && len(allResults) > maxResults {
- break
- }
- }
- return allResults, nil
- }
- // searchByToken 分词查询
- func searchByToken22(client *elastic.Client, projectName, province, city, publish string, maxResults int) ([]*elastic.SearchHit, error) {
- fieldsToTry := []string{"projectname.pname", "title", "detail"}
- filtersToTry := [][]elastic.Query{
- {elastic.NewTermsQuery("subtype", "中标", "成交", "合同", "单一")},
- {elastic.NewTermsQuery("toptype", "招标", "预告", "采购意向")},
- {elastic.NewTermsQuery("toptype", "拟建")},
- }
- analyzeResp, err := client.IndexAnalyze().
- Index("bidding").
- Analyzer("ik_smart").
- Text(projectName).
- Do(context.Background())
- if err != nil {
- return nil, err
- }
- var tokens []string
- for _, token := range analyzeResp.Tokens {
- tokens = append(tokens, token.Token)
- }
- if len(tokens) == 0 {
- return nil, fmt.Errorf("no tokens found from ik_smart")
- }
- queryText := strings.Join(tokens, " ")
- var allHits []*elastic.SearchHit
- seen := make(map[string]bool)
- for _, filter := range filtersToTry {
- query := elastic.NewBoolQuery().
- Must(elastic.NewMultiMatchQuery(queryText, fieldsToTry...).MinimumShouldMatch("100%")).
- Filter(filter...)
- searchResult, err := client.Search().
- Index("bidding").
- Query(query).
- Size(maxResults).
- Do(context.Background())
- if err != nil {
- continue
- }
- for _, hit := range searchResult.Hits.Hits {
- if !seen[hit.Id] {
- seen[hit.Id] = true
- allHits = append(allHits, hit)
- if len(allHits) >= maxResults {
- break
- }
- }
- }
- if len(allHits) >= maxResults {
- break
- }
- }
- return allHits, nil
- }
- func searchByToken(client *elastic.Client, projectName, province, city, publish string, maxResults int) ([]*elastic.SearchHit, error) {
- fieldsToTry := []string{"projectname.pname", "title", "detail"}
- filtersToTry := [][]elastic.Query{
- {elastic.NewTermsQuery("subtype", "中标", "成交", "合同", "单一")},
- {elastic.NewTermsQuery("toptype", "招标", "预告", "采购意向")},
- {elastic.NewTermsQuery("toptype", "拟建")},
- }
- // 解析时间
- var t time.Time
- var err error
- if publish != "" {
- t, err = time.Parse("200601", publish)
- if err != nil {
- log.Println("时间解析失败:", err)
- }
- }
- // 分词处理
- analyzeResp, err := client.IndexAnalyze().
- Index("bidding").
- Analyzer("ik_smart").
- Text(projectName).
- Do(context.Background())
- if err != nil {
- return nil, err
- }
- var tokens []string
- for _, token := range analyzeResp.Tokens {
- tokens = append(tokens, token.Token)
- }
- if len(tokens) == 0 {
- return nil, fmt.Errorf("no tokens found from ik_smart")
- }
- queryText := strings.Join(tokens, " ")
- // 指定返回字段
- fetchFields := elastic.NewFetchSourceContext(true).Include(
- "id", "title", "projectname", "projectcode", "bidamount", "area", "city",
- "toptype", "subtype", "buyer", "budget", "buyerperson", "buyertel",
- "s_winner", "winnertel", "agency", "publishtime")
- var allHits []*elastic.SearchHit
- seen := make(map[string]bool)
- for _, field := range fieldsToTry {
- var dateRangeStart, dateRangeEnd int64
- if !t.IsZero() {
- if field == "detail" {
- dateRangeStart, dateRangeEnd = getYearRange(t, 60)
- } else {
- dateRangeStart, dateRangeEnd = getYearRange(t, 36)
- }
- }
- for _, filters := range filtersToTry {
- var queries []*elastic.BoolQuery
- if field == "detail" {
- query := elastic.NewBoolQuery().
- Must(elastic.NewMatchQuery(field, queryText)).
- Filter(filters...)
- if !t.IsZero() {
- query = query.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, query)
- } else {
- // 省+市
- if province != "" && city != "" {
- q := elastic.NewBoolQuery().
- Must(elastic.NewMatchQuery(field, queryText)).
- Must(elastic.NewTermQuery("province", province)).
- Must(elastic.NewTermQuery("city", city)).
- Filter(filters...)
- if !t.IsZero() {
- q = q.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, q)
- }
- // 仅省
- if province != "" {
- q := elastic.NewBoolQuery().
- Must(elastic.NewMatchQuery(field, queryText)).
- Must(elastic.NewTermQuery("province", province)).
- Filter(filters...)
- if !t.IsZero() {
- q = q.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, q)
- }
- // 无省市
- q := elastic.NewBoolQuery().
- Must(elastic.NewMatchQuery(field, queryText)).
- Filter(filters...)
- if !t.IsZero() {
- q = q.Must(elastic.NewRangeQuery("publishtime").Gte(dateRangeStart).Lt(dateRangeEnd))
- }
- queries = append(queries, q)
- }
- for _, query := range queries {
- searchResult, err := client.Search().
- Index("bidding").
- Query(query).
- Size(maxResults).
- FetchSourceContext(fetchFields).
- Do(context.Background())
- if err != nil {
- continue
- }
- for _, hit := range searchResult.Hits.Hits {
- if !seen[hit.Id] {
- seen[hit.Id] = true
- allHits = append(allHits, hit)
- if len(allHits) >= maxResults {
- return allHits, nil
- }
- }
- }
- }
- }
- if field == "detail" && len(allHits) >= maxResults {
- break
- }
- }
- return allHits, nil
- }
- // searchCommon common 查询
- func searchCommon22(client *elastic.Client, projectName, province, city, publish string, maxResults int) ([]*elastic.SearchHit, error) {
- queryMap := map[string]interface{}{
- "bool": map[string]interface{}{
- "should": []interface{}{
- map[string]interface{}{"common": map[string]interface{}{"projectname.pname": map[string]interface{}{"query": projectName, "cutoff_frequency": 0.01, "low_freq_operator": "and", "boost": 0.2}}},
- map[string]interface{}{"common": map[string]interface{}{"title": map[string]interface{}{"query": projectName, "cutoff_frequency": 0.01, "low_freq_operator": "and", "boost": 0.2}}},
- map[string]interface{}{"common": map[string]interface{}{"detail": map[string]interface{}{"query": projectName, "cutoff_frequency": 0.01, "low_freq_operator": "and", "boost": 0.1}}},
- },
- "minimum_should_match": 1,
- },
- }
- queryBytes, _ := json.Marshal(queryMap)
- queryBase64 := base64.StdEncoding.EncodeToString(queryBytes)
- query := elastic.NewWrapperQuery(queryBase64)
- fetchFields := elastic.NewFetchSourceContext(true).Include("id", "title", "projectname", "projectcode", "bidamount", "area", "city", "toptype", "subtype", "buyer", "budget", "buyerperson", "buyertel", "s_winner", "winnertel", "agency", "publishtime")
- searchResult, err := client.Search().
- Index("bidding").
- Query(query).
- Size(maxResults).
- FetchSourceContext(fetchFields).
- Do(context.Background())
- if err != nil {
- return nil, err
- }
- var allHits []*elastic.SearchHit
- seen := make(map[string]bool)
- for _, hit := range searchResult.Hits.Hits {
- if !seen[hit.Id] {
- seen[hit.Id] = true
- allHits = append(allHits, hit)
- }
- }
- return allHits, nil
- }
- func searchCommon(client *elastic.Client, projectName, province, city, publish string, maxResults int) ([]*elastic.SearchHit, error) {
- fields := []string{"projectname.pname", "title", "detail"}
- var t time.Time
- var err error
- if publish != "" {
- t, err = time.Parse("200601", publish)
- if err != nil {
- log.Println("时间解析失败:", err)
- }
- }
- var allHits []*elastic.SearchHit
- seen := make(map[string]bool)
- fetchFields := elastic.NewFetchSourceContext(true).Include(
- "id", "title", "projectname", "projectcode", "bidamount", "area", "city",
- "toptype", "subtype", "buyer", "budget", "buyerperson", "buyertel",
- "s_winner", "winnertel", "agency", "publishtime")
- for _, field := range fields {
- var dateRangeStart, dateRangeEnd int64
- if !t.IsZero() {
- if field == "detail" {
- dateRangeStart, dateRangeEnd = getYearRange(t, 60)
- } else {
- dateRangeStart, dateRangeEnd = getYearRange(t, 36)
- }
- }
- var queries []map[string]interface{}
- commonQuery := func(f string, boost float64) map[string]interface{} {
- return map[string]interface{}{
- "common": map[string]interface{}{
- f: map[string]interface{}{
- "query": projectName,
- "cutoff_frequency": 0.01,
- "low_freq_operator": "and",
- "boost": boost,
- },
- },
- }
- }
- if field == "detail" {
- // 只做普通匹配 + 时间
- boolQuery := map[string]interface{}{
- "bool": map[string]interface{}{
- "must": []interface{}{
- commonQuery(field, 0.1),
- },
- },
- }
- if !t.IsZero() {
- boolQuery["bool"].(map[string]interface{})["filter"] = []interface{}{
- map[string]interface{}{
- "range": map[string]interface{}{
- "publishtime": map[string]interface{}{
- "gte": dateRangeStart,
- "lt": dateRangeEnd,
- },
- },
- },
- }
- }
- queries = append(queries, boolQuery)
- } else {
- // 1. 省+市
- if province != "" && city != "" {
- q := map[string]interface{}{
- "bool": map[string]interface{}{
- "must": []interface{}{
- commonQuery(field, 0.2),
- map[string]interface{}{"term": map[string]interface{}{"province": province}},
- map[string]interface{}{"term": map[string]interface{}{"city": city}},
- },
- },
- }
- if !t.IsZero() {
- q["bool"].(map[string]interface{})["filter"] = []interface{}{
- map[string]interface{}{
- "range": map[string]interface{}{
- "publishtime": map[string]interface{}{
- "gte": dateRangeStart,
- "lt": dateRangeEnd,
- },
- },
- },
- }
- }
- queries = append(queries, q)
- }
- // 2. 仅省
- if province != "" {
- q := map[string]interface{}{
- "bool": map[string]interface{}{
- "must": []interface{}{
- commonQuery(field, 0.2),
- map[string]interface{}{"term": map[string]interface{}{"province": province}},
- },
- },
- }
- if !t.IsZero() {
- q["bool"].(map[string]interface{})["filter"] = []interface{}{
- map[string]interface{}{
- "range": map[string]interface{}{
- "publishtime": map[string]interface{}{
- "gte": dateRangeStart,
- "lt": dateRangeEnd,
- },
- },
- },
- }
- }
- queries = append(queries, q)
- }
- // 3. 不加省市
- q := map[string]interface{}{
- "bool": map[string]interface{}{
- "must": []interface{}{
- commonQuery(field, 0.2),
- },
- },
- }
- if !t.IsZero() {
- q["bool"].(map[string]interface{})["filter"] = []interface{}{
- map[string]interface{}{
- "range": map[string]interface{}{
- "publishtime": map[string]interface{}{
- "gte": dateRangeStart,
- "lt": dateRangeEnd,
- },
- },
- },
- }
- }
- queries = append(queries, q)
- }
- for _, q := range queries {
- // 编码 query 为 base64
- queryBytes, _ := json.Marshal(q)
- queryBase64 := base64.StdEncoding.EncodeToString(queryBytes)
- query := elastic.NewWrapperQuery(queryBase64)
- searchResult, err := client.Search().
- Index("bidding").
- Query(query).
- Size(maxResults).
- FetchSourceContext(fetchFields).
- Do(context.Background())
- if err != nil {
- log.Println("searchCommon 查询失败:", err)
- continue
- }
- for _, hit := range searchResult.Hits.Hits {
- if !seen[hit.Id] {
- seen[hit.Id] = true
- allHits = append(allHits, hit)
- if len(allHits) >= maxResults {
- return allHits, nil
- }
- }
- }
- }
- }
- return allHits, nil
- }
- // getYearRange calculates a date range of +/- 1 year from the base date.
- func getYearRange(baseDate time.Time, m int) (start, end int64) {
- endTime := baseDate.AddDate(0, m, 0)
- startTime := baseDate.AddDate(0, -m, 0)
- return startTime.Unix(), endTime.Unix()
- }
|