需求 业务需求,查询在指定时间段过生日的人.如 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 =1701662559000 L;                 def end =1704340959000 L;                 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)  } 
 
参考