NumericRangeQuery giving wrong results

Hello,

I need to range query for an Integer field. I tried a lot and searched a lot too but I can’t make it work the way it should be, at least in my opinion. I was able to make it work with a PaddedIntegerBridge (Example under 4.4.3 in Hibernate Documentation)
but I would like to do it right (Point 4.4.1 says “Integer are per default indexed numerically using a Trie structure which allows for efficient range queries and sorting, resulting in better query response times.”)

Property look like this:

@Field(index = Index.YES, indexNullAs = "-1", analyze = Analyze.NO, store = Store.YES)
@Column(name = "ViewAgeInDays_Min")
private Integer minAgeInDays;

@NumericField was omitted because I read that it is not necessary and it does not change anything when used.

For testing I had two datasets with values 100 and 300.

+ViewAgeInDays_Min:[150 TO *]

gives both as result

+ViewAgeInDays_Min:[150 TO 700]

gives no result.

What am I missing here?
Thangs in advance!

Best regards

Hello,

  1. Did you reindex your data after you changed the annotations on your property?
  2. How do you create your query? Please give the exact code, including any use of the DSL and the type of your parameters.

Hello,

thanks for your quick reply and sorry for my late once.

Yes it is reindexed, I delete the hole folder nearly everytime when I deploy, just to make sure.

Because using Luke to check the queries also doesn’t give me the correct results I was assuming there is a problem with the index. Nevertheless here is my code, hopefully I’m boiling it down to the relevant parts:

private SearchResults getFilterResults(final SearchDto searchDto, final FullTextEntityManager em) {
		final QueryBuilder builder = em.getSearchFactory().buildQueryBuilder().forEntity(MyData.class).get();
		final MyDataQueryBuilder myDataQueryBuilder = new MyDataQueryBuilder(searchDto);
		final Query luceneQuery = myDataQueryBuilder.createBooleanQuery();
		final FullTextQuery textQuery = em.createFullTextQuery(luceneQuery, MyData.class);
		final List<?> list = textQuery.getResultList();
}

I’m building the strings on my own so it is easier to combine some queries

public BooleanQuery createBooleanQuery() {
	final BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
	for (final QueryDto queryDto : queryDtos) {
		final QueryParser queryParser = new MultiFieldQueryParser(queryDto.getIndex(), new StandardAnalyzer());
		Query luceneQuery = null;
		try {
			luceneQuery = queryParser.parse(convertSearchString(queryDto.getWert()));
		} catch (final ParseException e) {
			LOG.debug(e.getMessage());
		}
		booleanQueryBuilder.add(luceneQuery, queryDto.getOccur());
	}
	return booleanQueryBuilder.build();
}

but I also tried this

final NumericRangeQuery<Integer> numericRangeQuery = NumericRangeQuery
	.newIntRange("viewAgeInDays.ViewAgeInDays_Min", 150, 350, true, true);

with the same outcome.

For LocalDate I had to make the same workaround and I hope if you can help me fix this the range query for localDates will also be fixed.

Thanks for your help.
Best regards

The numeric range query seems to be using a different field name than your other queries (viewAgeInDays.ViewAgeInDays_Min instead of ViewAgeInDays_Min). Could this be the problem?

For the query parser, a bit of explanation will be necessary…

First, you need to understand text and numeric data are stored differently in Lucene. If your execute a text range query on a numeric field, you won’t get any match, and vice-versa.

When you map your Integer property without any bridge, you index data in a numeric field. When you map your Integer property with the PaddedIntegerBridge (old solution), you index data in a text field.

When using the query parser, you always generate a text range query. Always. So that approach cannot work with a numeric field.

That should explain some of the problems you are experiencing.

Also, when using the query parser, field bridges are not applied automatically. So the padding applied by your “padding” bridge, in particular, will not be applied, probably resulting in confusing matches.

If you need to deal with more than just text fields, I’d recommend moving away from the query parser and building your queries with the query DSL instead. These queries in particular will be useful:

  • keyword queries for exact matches. It supports both text and numeric fields; just pass an argument of the same type as your entity property (String, Integer, Date, …)
  • range queries. It supports both text and numeric fields; just pass an argument of the same type as your entity property (String, Integer, Date, …)
  • simple query strings for text fields only.
  • And more.
1 Like

Hello yrodiere!

Thanks for your help!

“viewAgeInDays.ViewAgeInDays_Min” was an copy & past error, I’m using the right one.
The important part to know is, that the query parser always generates a text range query!
I’m also using query DSL now and doing this now

if (nqd.getFrom() > 0) {
	final Query fromRangeQuery = builder.range().onField(nqd.getIndexFrom()).from(nqd.getFrom())
		.to(Integer.MAX_VALUE).createQuery();
	booleanQueryBuilder.add(fromRangeQuery, BooleanClause.Occur.MUST);
}
if (nqd.getTo() > 0) {
	final Query toRangeQuery = builder.range().onField(nqd.getIndexTo()).from(0)
		.to(nqd.getTo()).createQuery();
	booleanQueryBuilder.add(toRangeQuery, BooleanClause.Occur.MUST);
}

Now everything works as expected. :slight_smile:
Sadly I’m trying the same with my LocaleDateTime and it’s not working but I guess I have to open a new thread for this.

Thanks a lot!

Best regards

It would have been fine if I really would have used LocalDateTime but I was using LocalDate instead. My bad, everything is working fine now!

Thanks again for your help!

Glad this helped. Thanks for the feedback!