需求 业务需求,查询在指定时间段过生日的人.如 2-28 到 9-15 之间过生日的人
解决方案 业务存储有生日的毫秒级时间戳 ‘birthday’
mysql 1 2 3 select  *  from  user  where  DATE_FORMAT(FROM_UNIXTIME(birthday/ 1000 ),'%m-%d' ) BETWEEN  '02-28'  AND  '09-15' ; 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SELECT  *  FROM   user  WHERE DATE_ADD(FROM_UNIXTIME(birthday/ 1000 ),              INTERVAL  YEAR (CURDATE())- YEAR (FROM_UNIXTIME(birthday/ 1000 ))                         +  IF(DAYOFYEAR(CURDATE()) >  DAYOFYEAR(FROM_UNIXTIME(birthday/ 1000 )),1 ,0 ) YEAR )               BETWEEN  CURDATE() AND  DATE_ADD(CURDATE(), INTERVAL  30  DAY ); SELECT  *  FROM   user  WHERE DATE_ADD(FROM_UNIXTIME(birthday/ 1000 ),              INTERVAL  YEAR (FROM_UNIXTIME(1701662559000 / 1000 ))- YEAR (FROM_UNIXTIME(birthday/ 1000 )) +  IF(DAYOFYEAR(FROM_UNIXTIME(1701662559000 / 1000 )) >  DAYOFYEAR(FROM_UNIXTIME(birthday/ 1000 )),1 ,0 ) YEAR )   BETWEEN  FROM_UNIXTIME(1701662559000 / 1000 ) AND  FROM_UNIXTIME(1704340959000 / 1000 );
es 方案一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 GET  user / _search{   "query": {     "bool": {       "filter": [         {           "exists": {"field": "birthday"}         },         {           "script": {             "script": {               "source":                """               def date = Instant.ofEpochMilli(doc['birthday'].value).atZone(ZoneId.of("Asia/ Shanghai"));               def month = date.getMonthValue();               def day = date.getDayOfMonth();               return (month == 2  && day >= 28) || (month > 2 && month < 9) || (month == 9 && day <= 15);               """             }           }         },         {           "range": {             "birthday": {             "gt": 0              }           }         }       ]     }   } } 
方案二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 GET  user / _search{   "query": {     "bool": {       "filter": [         {           "exists": {"field": "birthday"}         },         {           "script": {             "script": {               "source":                """                 def start=1701662559000L;                 def end=1704340959000L;                 def startTime = Instant.ofEpochMilli(start).atZone(ZoneId.of("Asia/ Shanghai"));                 def endTime= Instant.ofEpochMilli(end).atZone(ZoneId.of("Asia/ Shanghai"));                  def birthdayTime = Instant.ofEpochMilli(doc['birthday'].value).atZone(ZoneId.of("Asia/ Shanghai"));                 def birthdayDate = birthdayTime.toLocalDate();                 def startTimeDate=startTime.toLocalDate();                 def endTimeDate=endTime.toLocalDate();                           def a=LocalDate.of(startTimeDate.getYear(), birthdayDate.getMonthValue(),birthdayDate.getDayOfMonth())                     .atStartOfDay().atZone(ZoneId.of("Asia/ Shanghai"));                 def b=LocalDate.of(endTimeDate.getYear(), birthdayDate.getMonthValue(),birthdayDate.getDayOfMonth())                     .atStartOfDay().atZone(ZoneId.of("Asia/ Shanghai"));                         return (a.isAfter(startTime) && a.isBefore(endTime)) || (b.isAfter(startTime) && b.isBefore(endTime));               """             }           }         },         {           "range": {             "birthday": {             "gt": 0              }           }         }       ]     }   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 long  start=1706517776000L ;long  end=1714809776000L ;ZonedDateTime  startTime  =  Instant.ofEpochMilli(start).atZone(ZoneId.of("Asia/Shanghai" ));ZonedDateTime endTime= Instant.ofEpochMilli(end).atZone(ZoneId.of("Asia/Shanghai" )); ZonedDateTime  birthdayTime  =  Instant.ofEpochMilli(228096000000L ).atZone(ZoneId.of("Asia/Shanghai" ));LocalDate  birthdayDate  =  birthdayTime.toLocalDate();LocalDate  startTimeDate=startTime.toLocalDate(); LocalDate  endTimeDate=endTime.toLocalDate(); ZonedDateTime a=LocalDate.of(startTimeDate.getYear(), birthdayDate.getMonthValue(),birthdayDate.getDayOfMonth())     .atStartOfDay().atZone(ZoneId.of("Asia/Shanghai" )); ZonedDateTime b=LocalDate.of(endTimeDate.getYear(), birthdayDate.getMonthValue(),birthdayDate.getDayOfMonth())     .atStartOfDay().atZone(ZoneId.of("Asia/Shanghai" )); return  (a.isAfter(startTime) && a.isBefore(endTime))||(b.isAfter(startTime) && b.isBefore(endTime));
使用go的package(“github.com/olivere/elastic/v7”)实现上述查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 boolQuery := elastic.NewBoolQuery().Filter(    elastic.NewRangeQuery("birthday" ).Gt(0 ),    elastic.NewExistsQuery("birthday" ),    elastic.NewScriptQuery(elastic.NewScript(fmt.Sprintf(                `def start=%dL;                  def end=%dL;                 def startTime = Instant.ofEpochMilli(start);                 def endTime= Instant.ofEpochMilli(end);                  def birthdayTime = Instant.ofEpochMilli(1702662559000L);                 def birthdayDate = birthdayTime.atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();                 def startTimeDate=startTime.atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();                 def endTimeDate=endTime.atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();                           def a=LocalDate.of(startTimeDate.getYear(), birthdayDate.getMonthValue(),birthdayDate.getDayOfMonth())                     .atStartOfDay().atZone(ZoneId.of("Asia/Shanghai")).toInstant();                 def b=LocalDate.of(endTimeDate.getYear(), birthdayDate.getMonthValue(),birthdayDate.getDayOfMonth())                     .atStartOfDay().atZone(ZoneId.of("Asia/Shanghai")).toInstant();                         return (a.isAfter(startTime) && a.isBefore(endTime))||(b.isAfter(startTime) && b.isBefore(endTime));` ,                birthdayStart, birthdayEnd)),   ))    searchResult, err := esClient.Search().Index("user" ).Query(boolQuery).Do(context.Background())    if  err != nil  {   fmt.Printf("Error executing search: %v\n" , err)   return   }    for  _, hit := range  searchResult.Hits.Hits {      fmt.Printf("Document ID: %s\n" , hit.Id)  } 
参考