GroupQueryNodeProcessor doesn't recursively process children of custom query nodes [LUCENE-3367]
- Dominant language
- Java
- Stars
- 3.6k
- Forks
- 1.4k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 88
Description
In some situations I found that boolean queries weren't using the default operator. I have tracked this issue down to GroupQueryNodeProcessor, which does not appear to be recursing into the tree.
I have two unit tests. The first one has just the boolean query, the second one has a custom query node wrapped around it. In the second case, the default operator logic is not applied to the boolean query.
```Java
`@Test`
public void testDefaultOperator() throws Exception
{
QueryNode node = new GroupQueryNode(new BooleanQueryNode(Arrays.asList(
new FieldQueryNode("text", "a", 1, 1),
new FieldQueryNode("text", "b", 3, 3)
)));
GroupQueryNodeProcessor processor = new GroupQueryNodeProcessor();
QueryConfigHandler config = new StandardQueryConfigHandler();
config.addAttribute(DefaultOperatorAttribute.class).setOperator(DefaultOperatorAttribute.Operator.AND);
processor.setQueryConfigHandler(config);
QueryNode actualNode = processor.process(node);
QueryNode expectedNode = new BooleanQueryNode(Arrays.asList(
new BooleanModifierNode(new FieldQueryNode("text", "a", 1, 1), ModifierQueryNode.Modifier.MOD_REQ),
new BooleanModifierNode(new FieldQueryNode("text", "b", 3, 3), ModifierQueryNode.Modifier.MOD_REQ)
));
assertEquals("Wrong node after processing", expectedNode.toString(), actualNode.toString());
}
`@Test`
public void testDefaultOperatorInsideCustomNode() throws Exception
{
QueryNode node = new CustomQueryNode(Arrays.asList(new GroupQueryNode(new BooleanQueryNode(Arrays.asList(
new FieldQueryNode("text", "a", 1, 1),
new FieldQueryNode("text", "b", 3, 3)
)))));
GroupQueryNodeProcessor processor = new GroupQueryNodeProcessor();
QueryConfigHandler config = new StandardQueryConfigHandler();
config.addAttribute(DefaultOperatorAttribute.class).setOperator(DefaultOperatorAttribute.Operator.AND);
processor.setQueryConfigHandler(config);
QueryNode actualNode = processor.process(node);
QueryNode expectedNode = new CustomQueryNode(Arrays.asList(new GroupQueryNode(new BooleanQueryNode(Arrays.asList(
new BooleanModifierNode(new FieldQueryNode("text", "a", 1, 1), ModifierQueryNode.Modifier.MOD_REQ),
new BooleanModifierNode(new FieldQueryNode("text", "b", 3, 3), ModifierQueryNode.Modifier.MOD_REQ)
)))));
assertEquals("Wrong node after processing", expectedNode.toString(), actualNode.toString());
}
public static class CustomQueryNode extends QueryNodeImpl
{
private CustomQueryNode(List children)
{
setLeaf(false);
allocate();
set(children);
}
`@Override`
public CharSequence toQueryString(EscapeQuerySyntax escaper)
{
StringBuilder builder = new StringBuilder(100);
builder.append("custom(");
String separator = "";
for (QueryNode child : getChildren())
{
builder.append(separator);
builder.append(child.toQueryString(escaper));
separator = ",";
}
builder.append(')');
return builder.toString();
}
`@Override`
public String toString()
{
StringBuilder builder = new StringBuilder(100);
builder.append("\n");
for (QueryNode child : getChildren())
{
builder.append(child).append('\n');
}
builder.append("\n");
return builder.toString();
}
}
```
---
Migrated from [LUCENE-3367](https://issues.apache.org/jira/browse/LUCENE-3367) by Trejkaz
Contributor guide
Research direction
Locate GroupQueryNodeProcessor and inspect how it traverses QueryNode children. Reproduce the supplied testDefaultOperator and testDefaultOperatorInsideCustomNode cases, comparing processing of GroupQueryNode with CustomQueryNode. Done means the default AND operator is applied inside the custom node without changing the expected query structure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- search
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100