Hibernate Search 6中LocalDateTime的范围查询

彼得L355

我打算从Hibernate Search 5.11切换到6,但是找不到在LocalDateTime上查询DSL进行范围查询的方法。我更喜欢使用本机Lucene QueryParser。在以前的版本中,我使用了NumericRangeQuery,因为使用了@FieldBridge(转换为long值)。

这是我以前的版本代码。

    @Entity 
    ...
       @NumericField //convert to long value
        @FieldBridge(impl = LongLocalDateTimeFieldBridge.class) 
        @Field(index = Index.YES, analyze = Analyze.NO, store = Store.NO)
        private LocalDateTime createDate;
...

这些是QueryParser

     public class NumericLocalDateRangeQueryParser extends QueryParser {
    
        private static final Logger logger = LogManager.getLogger();
        private String f;
        private static final Long DEFAULT_DATE = -1L;
        private String dateFormat;
        public NumericLocalDateRangeQueryParser(final String f, final Analyzer a) {
            super(f, a);
            this.f = f;
        }
    
        public NumericLocalDateRangeQueryParser(final String dateFormat,final String f, Analyzer a) {
            super(f, a);
            this.f = f;
            this.dateFormat = dateFormat;
            logger.debug("date formate: {}", ()->dateFormat);
        }
    
          
        //check a field if found, have to set to -1
        @Override
        protected Query newFieldQuery(Analyzer analyzer, String field, String queryText, boolean quoted) throws ParseException {
            if (f.equals(field)) {
                 try {
                     return NumericRangeQuery.newLongRange(
                            field,
                            stringToTime(queryText).toEpochDay(), stringToTime(queryText).toEpochDay(),
                            true,
                            true
                    );
                } catch (final DateTimeParseException ex) {
                    
                    return super.newFieldQuery(analyzer, field, queryText, quoted);
                     
                }
            }
          
            return super.newFieldQuery(analyzer, field, queryText, quoted);  
        }
    
        /**
         *
         * @param field = filed when indexing
         * @param part1 = date 1 e.g. date 1 to date 2 in string
         * @param part2 = date 2
         * @param startInclusive
         * @param endInclusive
         * @return
         */
        @Override
        protected Query newRangeQuery(final String field, final String part1, final String part2,
                final boolean startInclusive, final boolean endInclusive) {
    
            if (f.equals(field)) {
    
                try {
                    return NumericRangeQuery.newLongRange(
                            field,
                            stringToTime(part1).toEpochDay(), stringToTime(part2).toEpochDay(),
                            true,
                            true
                    );
    
                } catch (final DateTimeParseException ex) {
                    return NumericRangeQuery.newLongRange(field, DEFAULT_DATE, DEFAULT_DATE, true, true);
                }
            } else {
                return super.newRangeQuery(field, part1, part2, startInclusive, endInclusive);
            }
        }
    
        @Override
        protected org.apache.lucene.search.Query newTermQuery(final Term term) { 
 if (term.field().equals(f)) {
                try {
                    return NumericRangeQuery.newLongRange(term.field(),
                            stringToTime(term.text()).toEpochDay(), stringToTime(term.text()).toEpochDay(), true, true);
    
                } catch (final DateTimeParseException ex) {
                    logger.debug("it's not numeric: {}", () -> ex.getMessage());
                    return NumericRangeQuery.newLongRange(field, DEFAULT_DATE,DEFAULT_DATE, true, true);
                }
            } else {
                logger.debug("normal query term");
                return super.newTermQuery(term);
            }
        }
    
        private LocalDate stringToTime(final String date) throws DateTimeParseException {
           final  DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
            return LocalDate.parse(date, formatter);
    
        }
       
    }
耶罗地尔

首先,在映射方面,您只需要这样做:

       @GenericField
       private LocalDateTime createDate;

第二,查询。如果您真的想编写本机查询并跳过整个Search DSL,我想您有理由。您愿意在评论中分享它们吗?也许它将给我一些改进Hibernate Search的想法。

无论如何,基础查询改变Lucene的5和8之间有很多你可以找到我们如何基于查询的长字段(如LocalDateTime在这里,以及我们如何转换LocalDateTime为长在这里

因此,这样的事情应该起作用:

long part1AsLong = stringToTime(part1).toInstant(ZoneOffset.UTC).toEpochMilli();
long part2AsLong = stringToTime(part2).toInstant(ZoneOffset.UTC).toEpochMilli();
Query query = LongPoint.newRangeQuery(field, part1AsLong, part2AsLong);

或者,如果您可以依靠Search DSL,则可以执行以下操作:

SearchSession searchSession = Search.session(entityManager);
SearchScope<MyEntity> scope = searchSession.scope(MyEntity.class);
// Pass the scope to your query parser somehow
MyQueryParser parser = new MyQueryParser(..., scope);

// Then in your parser, do this to create a range query on a `LocalDateTime` field:
LocalDateTime part1AsDateTime = stringToTime(part1);
LocalDateTime part2AsDateTime = stringToTime(part2);
Query query = LuceneMigrationUtils.toLuceneQuery(scope.predicate().range()
        .field(field)
        .between(part1AsDateTime, part2AsDateTime)
        .toPredicate());

但是请注意,这LuceneMigrationUtils是SPI,因此它可能会更改或在更高版本中删除。如果您认为它有用,我们可以在将来的版本中将其作为API公开,以确保可以保留在那里。


我怀疑我们可以通过在Hibernate Search中添加一些内容来更好地解决您的问题。为什么确切地需要依赖查询解析器?

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Hibernate Search中将范围查询与关键字查询结合在一起?

带有枚举字段的Hibernate Search / Lucene范围查询不返回任何结果

如何在Hibernate Search / Lucene中禁用默认评分/增强功能?

使用Hibernate Search查询并获得所有项目而无需分页

在Hibernate Search中索引数据

在Web应用程序中启动Hibernate Search时出错

使用Hibernate Search自动完成

Hibernate Search查询多个实体

Hibernate Search 5.0数值Lucene查询HSEARCH000233问题

Hibernate Search直接计数,而不是使用Lucene和Elasticsearch进行常规查询

Hibernate-Search 6和Elasticsearch集成

Hibernate Search查询类

Hibernate Search索引单个租户

Hibernate Search 5中的访问目录

org.hibernate.HibernateException:在Hibernate Search中建立索引时出错(在事务完成之前)

Hibernate Search不为数据库中的项目建立索引

在数据库中搜索文本(使用Hibernate Search)

使用Hibernate Search查询枚举(枚举)的IndexedEmbedded列表

如何在Hibernate Search中有意忽略过滤器的子查询?

Hibernate Search - 在查询上应用 facet 不会返回任何结果

如何在 Hibernate Lucene Search 中添加多个限制?

使用 Hibernate Search 时“过滤查询不支持排序”

Hibernate Search 在多租户 Spring Boot 应用程序中初始化索引

Hibernate Search 中 BigDecimal 的范围查询

如何在 Hibernate-search 中索引继承的字段?

Hibernate Search:如何查询父类中的字段?

Hibernate Search:将 Lucene 索引持久化到数据库中

带有 Lucene 荧光笔和同义词列表的 Hibernate Search 6

Hibernate Search:在没有数据库事务的情况下执行搜索查询