Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixing NativeQuery with CriteriaQuery and a Criteria with GeoLocation fails #2840

Closed
bernhardkern opened this issue Jan 31, 2024 · 10 comments · Fixed by #2846
Closed

Mixing NativeQuery with CriteriaQuery and a Criteria with GeoLocation fails #2840

bernhardkern opened this issue Jan 31, 2024 · 10 comments · Fixed by #2846
Labels
type: bug A general bug

Comments

@bernhardkern
Copy link

bernhardkern commented Jan 31, 2024

Mixing a NativeQuery and a CriteriaQuery fails, when using Criteria with geoLocation.

Version: Spring Data ElasticSearch 5.2.2
Spring Boot Version: 3.2.2
ElasticSearch Version: 8.12.0

Github, Service demonstrating the issue

Github, Test demonstrating the issue

 val nativeGeoDistance = GeoDistanceQuery.Builder().field("location").distance("10km")            
 .location(GeoLocation.Builder().latlon(LatLonGeoLocation.Builder().lat(pointWeAreLookingFor.lat).lon(pointWeAreLookingFor.lon).build()).build()).build()
        val nq = NativeQueryBuilder().withQuery { q -> q.geoDistance(nativeGeoDistance) }.build()

        return operations.search(nq, WithGeoLocation::class.java)

delivers the expected result -> only one document is found

val cq = CriteriaQuery(Criteria("location").within(pointWeAreLookingFor, "10km"))
        val nq = NativeQueryBuilder().withQuery(cq).build()

        return operations.search(nq, WithGeoLocation::class.java)

fails, both documents are found. It also fails with bounding box queries. Everything that is geo-related.

If I run the critieriaQuery directly, without nesting it in NativeQuery, it works. Sometimes this nesting is necessary, e.g. when using Aggregations, but in general we write the Queries in CriteriaQuery.

Issue: Using a CriteriaQuery as base for the NativeQueryBuilder fails when using a geo based query. Other critiera work (e.g. Term).

@bernhardkern bernhardkern changed the title Mixing NativeQuery with CriteriaQuery and a Criteria with Geo Query fails Mixing NativeQuery with CriteriaQuery and a Criteria with GeoLocation fails Jan 31, 2024
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 31, 2024
@sothawo
Copy link
Collaborator

sothawo commented Jan 31, 2024

Had a first look at the sample repo; alas there is no explicit Spring Data Elasticsearch configuration, so I cannot just plug in an intercepting proxy to see what's going over the line. I will need to set this up in a configurable way.

@sothawo
Copy link
Collaborator

sothawo commented Jan 31, 2024

BTW, If you are using Elasticsearch 8.12, be aware that Elasticsearch broke the communication at one place between the client and the server, the problem comes from the server side, so it will happen with a client lib of 8.11 as well, see #2836 and the issues linked there

@sothawo
Copy link
Collaborator

sothawo commented Feb 5, 2024

Ok, had some time to debug this now.

A CriteriaQuery can have criteria that are defining the query part of a search, and other ones used in the filter part of a search. A geo_location within criteria is one for the filter part. And this currently is only added to the search when using a CriteriaQuery directly, not when it's added to a NativeQuery. And so in your example the whole query is basically ignored resultig inreturning all documents from the index.

So we need to fix that for a CriteriaQuery in a NativeQuery we not only add the query but also the filter part.

@sothawo sothawo added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 5, 2024
sothawo added a commit to sothawo/spring-data-elasticsearch that referenced this issue Feb 6, 2024
sothawo added a commit that referenced this issue Feb 6, 2024
Original Pulle Request #2846
Closes #2840
@sothawo sothawo added this to the 5.3 M1 (2024.0.0) milestone Feb 6, 2024
sothawo added a commit that referenced this issue Feb 6, 2024
Original Pull Request #2846
Closes #2840

(cherry picked from commit e9ecebd)
sothawo added a commit that referenced this issue Feb 6, 2024
Original Pull Request #2846
Closes #2840

(cherry picked from commit e9ecebd)
(cherry picked from commit 310f0ed)
@sothawo
Copy link
Collaborator

sothawo commented Feb 6, 2024

backported to 5.2.x and 5.1.x

@bernhardkern
Copy link
Author

Thx for fixing!

@mateuszszewczyk
Copy link

So we need to fix that for a CriteriaQuery in a NativeQuery we not only add the query but also the filter part.

The fix indeed works, but only when aggregation is not used, as the filtering added by criteria, for example, criteria.and(new Criteria("addressLocation").within(geoPoint, "15m"));, is added as a post_filter rather than as a filter in the query. This leads to issues because the aggregation is returned for the entire index rather than for the search results.

var criteria = new Criteria("addressCountry").is(country);
        if (StringUtils.isNotEmpty(request.getLat()) && StringUtils.isNotEmpty(request.getLng())) {
            var geoPoint = new GeoPoint(Double.parseDouble(request.getLat()), Double.parseDouble(request.getLng()));
            criteria.and(new Criteria("addressLocation").within(geoPoint, "15m"));
        }
{
    "aggregations": {
        "test_aggregation": {
            "terms": {
                "field": "test",
                "size": 2147483647
            }
        }
    },
    "from": 0,
    "post_filter": {
        "geo_bounding_box": {
            "address_location": {
                "bottom_right": {
                    "lat": 52.1747983647779,
                    "lon": 21.0412053143817
                },
                "top_left": {
                    "lat": 52.2135742278123,
                    "lon": 20.9395817792254
                }
            }
        }
    },
    "query": {
        "bool": {
            "must": [
                {
                    "query_string": {
                        "default_operator": "and",
                        "fields": [
                            "address_country"
                        ],
                        "query": "EN"
                    }
                }
            ]
        }
    }

@sothawo
Copy link
Collaborator

sothawo commented Feb 24, 2024

I see, that only comes up when using the CriteriaQuery in the native query context. As far as I see filters can be either post filter or be set within a bool query. As a CriteriaQuery always is built as a bool query it might be possible to move the filter part inside the query. Have to check if this breaks anything (#2857)

@bernhardkern
Copy link
Author

Hi @sothawo

The fix works for the SearchHits, but does not work for Aggregations. I tested the new code with spring-data-elasticsearch 5.3.0-M2.

I added another test as a showcase in the repository
Github, Service demonstrating the issue

Github, Test demonstrating the issue

it adds this to the NativeQuery:

.withAggregation(
                "exampleAggregation",
                Aggregation.of { it.terms(TermsAggregation.Builder().field("aggregationId").size(20).build()) },
            )

and this to the test:


result shouldHaveSize 3 // **works with spring-data-elasticsearch 5.3.0-M2**

val foundAggregationIds = (result.aggregations as ElasticsearchAggregations)
    .aggregationsAsMap()["exampleAggregation"]
        ?.aggregation()
        ?.aggregate?.lterms()
        ?.buckets()?.array()
        ?.map { it.key() }?.toSet() ?: emptySet()

I persist 4 documents and want to find 3 documents. After the upgrade to 5.3.0-M2, the result contains the expected 3 results, but the aggregation still contains all 4 documents.

I can also create a new ticket, if this would be easier, please tell me what you prefer.
Thx.

@sothawo
Copy link
Collaborator

sothawo commented Apr 12, 2024

That is what I wrote in my last comment: the geolocation filter is set as a post filter and so it does affect the query but not the aggregation. There is already #2857 to see if this can be changed, so there is no need for a new issue.

@bernhardkern
Copy link
Author

Thx for the explanation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants