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

QueryDSL: $and and $or with more than two arguments in final query document [DATAMONGO-2475] #3330

Closed
spring-projects-issues opened this issue Feb 15, 2020 · 3 comments
Assignees

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Feb 15, 2020

Hencxjo opened DATAMONGO-2475 and commented

I had to build a big QueryDSL predicate to fetch documents. As result, I get an exception; because the depth of the document used by MongoTemplate was greater than the maximum depth limits.

Using Spring Data MongoDB's Criteria I achieved this query with no errors. Criteria's API defines two different operations: and(...) and andOperator(...). QueryDSL has nothing similar to that, but I think we don't need a different operation.

MongodbDocumentSerializer is used to create the final query that eventually will be used by MongoTemplate. This serializer should create documents with the minimum depth as possible.

I actually coded a solution to this (from branch 2.2.x) and tested it. This change removes nested "$or" in "$or" operations, and nested "$and" in "$and" operations, generating just one logical operator. In case of an "$and", this code keeps merging documents with different properties; same way it does now.

 

How does it work? What do I expect?

Using QueryDSL we can build a predicate like this:

QPerson.person.firstname.eq("Hencxjo")
    .or(QPerson.person.lastname.eq("Leon"))
    .or(QPerson.person.age.loe(30))
    .or(QPerson.person.age.qoe(20))
    .or(QPerson.person.uniqueId.isNull())

The final document that MongoTemplate will use for querying will be:

{
  "$or": [
    {
      "$or": [
        {
          "$or": [
            {
              "$or": [
                { "firstname": "Hencxjo" },
                { "lastname": "Leon" }
              ]
            },
            { "age": { "$lte": 30 } }
          ]
        },
        { "age": { "$gte": 20 } }
      ]
    },
    { "uniqueId": { "$exists": false } }
  ]
}

What I want to get:

{
 "$or": [
   { "firstname": "Hencxjo" },
   { "lastname": "Leon" },
   { "age": { "$lte": 30 } },
   { "age": { "$gte": 20 } },
   { "uniqueId": { "$exists": false } }
 ]
}

In case of chained ANDs, this may be the result:

{
  "$and": [
    {
      "firstname": "Hencxjo",
      "lastname": "Leon",
      "age": { "$lte": 30 },
      "uniqueId": { "$exists": false }
    },
    { "age": { "$gte": 20 } }
  ]
}

 


Affects: 2.2.4 (Moore SR4)

Reference URL: https://docs.mongodb.com/manual/reference/limits/

Referenced from: pull request #834

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Feb 15, 2020

Hencxjo commented

Pull request: #834

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Feb 20, 2020

Christoph Strobl commented

Thanks for getting in touch! We'll look into this

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Apr 14, 2020

Hencxjo commented

Will this change be merged to branch 2.2.x?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants