boolQuery: nested clauses and dynamically adding new ones


(drjz) #1

Hi all,

I am using the Java client. I am using QueryBuilders.boolQuery() to dynamically construct a DSL bool query for a nested object field. Example query looks this and it part of a query. This query could grow given the number of clauses. The idea is that the user can search for other standard fields AND the nested object fields. The standard fields are in a separate boolQuery and the nested object field in this one. What I want to do is to express the following example query using the boolQuery: cats AND (dog OR horse OR pig).

Question: how can I dynamically add new clauses if the QueryBuilder is already nested with multiple boolQueries in it?

{
      "bool" : {
        "must" : {
          "bool" : {
            "should" : [ {
              "nested" : {
                "query" : {
                  "bool" : {
                    "must" : {
                      "query_string" : {
                        "query" : "raw:(dog)",
                        "default_operator" : "and"
                      }
                    } 
                  }
                },
                "path" : "path"
              }
            }, {
              "nested" : {
                "query" : {
                  "bool" : {
                    "must" : {
                      "query_string" : {
                        "query" : "raw:(horse)",
                        "default_operator" : "and"
                      }
                    }
                  }
                },
                "path" : "path"
              }
            }, {
              "nested" : {
                "query" : {
                  "bool" : {
                    "must" : {
                      "query_string" : {
                        "query" : "raw:(pig)",
                        "default_operator" : "and"
                      }
                    }
                  }
                },
                "path" : "path"
              }
            } ]
          }
        }
      }
    }

(Adrien Grand) #2

Hi,

It might be easier to use a different intermediate representation for your query and only translate it to an Elasticsearch query at the last moment.

Also note that this kind of query would be much faster if you copied data from your nested docs to the parent document given that you don't need nested documents here.


(drjz) #3

I have tried to create intermediate steps, but then I am getting a StackOverflowError. I am trying to embed a new QueryBuilder object in an existing one. Do you know whether/how this is possible?

BoolQueryBuilder queryBuilderNew = new BoolQueryBuilder();

queryBuilderNew
		.should(QueryBuilders.nestedQuery(nestedPath, QueryBuilders.boolQuery()
				.must(QueryBuilders.queryString(field + ":(horse)").defaultOperator(QueryStringQueryBuilder.Operator.AND))
		))
		.should(QueryBuilders.nestedQuery(nestedPath, QueryBuilders.boolQuery()
				.must(QueryBuilders.queryString(field + ":(pig)").defaultOperator(QueryStringQueryBuilder.Operator.AND))
		));

queryBuilderNew.must(queryBuilderNew);

(Adrien Grand) #4

You can't embed a boolean query into itself. It's like creating a query that would be a AND (a AND (a AND ( a AND ...))).


(system) #5