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