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

Chaining Criteria does not produce the expected parenthesization [DATASOLR-105] #225

Closed
spring-projects-issues opened this issue Jul 18, 2013 · 8 comments

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Jul 18, 2013

Anssi Törmä opened DATASOLR-105 and commented

I have a Solr core representing employees. The schema includes these fields

  • id: long values stored and indexed
  • text: a catch-all text index constructed from employee name and other text but NOT the id field

In the index, there is an employee named "Anssi Törmä" (name indexed) with id 40764.

My goal is to dynamically, using Criteria, build a SolrQuery query that finds employees where the text contains words starting with given keywords OR, if a keyword is a number, employees with ID in the set input numbers.

From keywords "anssi" and "40764" my code builds criterion that is the same as

Criteria c = Criteria.where("text").startsWith("anssi")
		.and(Criteria.where("text").startsWith("40764"))
		.or(Criteria.where("id").is(40764));

I expect that the criterion would find the above-mentioned person because although the text does not match (does not contain the ID), the ID search does match.

I can see that the query built from the criteria is translated to the Solr query text:anssi* AND text:40764* OR id:40764. However, that query does not return any results, apparently because it doesn't have the correct parenthesization. A query that produces the expected results is ((text:anssi* AND text:40764*) OR id:40764)


Affects: 1.0 RC1, 1.0 GA

Attachments:

Issue Links:

2 votes, 4 watchers

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jul 18, 2013

Christoph Strobl commented

Hi,
at this time there is no support for parenthesization when chaining Critiera.
This issue is related to DATASOLR-71 for which I was not able to find a solution yet.

So I unfortunately still have to propose usage of SimpleStringCritiera or @Query.

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jul 19, 2013

Anssi Törmä commented

I got my test case to work by making QueryParser.createQueryStringFromCriteria(Criteria) nest all the criteria in parentheses:

String createQueryStringFromCriteria(Criteria criteria) {
	StringBuilder query = new StringBuilder(StringUtils.EMPTY);
	
	// Opening parentheses of nested criteria
	List<Criteria> chain = criteria.getCriteriaChain();
	for (int i = 0; i < chain.size(); i++) {
		query.append("(");
	}
	
	ListIterator<Criteria> chainIterator = chain.listIterator();
	while (chainIterator.hasNext()) {
		Criteria chainedCriteria = chainIterator.next();
		
		query.append(createQueryFragmentForCriteria(chainedCriteria));
		query.append(")"); // close the criterion

		if (chainIterator.hasNext()) {
			query.append(chainIterator.next().getConjunctionOperator());
			chainIterator.previous();
		}
	}

	return query.toString();
}

Would this help?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jul 24, 2013

Christoph Strobl commented

Hi, sorry for delayed answer. Will try to have a closer look next week.
Thank you already for the time invested!
Cheers, Christoph

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jul 25, 2013

Anssi Törmä commented

The parenthesization method I used only ensures evaluation in the same order that the criteria were chained in java code.

I suppose an arbitrary parenthesization like

(f1:v1 OR f2:v2) AND (f3:v3 OR f4:v4)

from

Criteria c1 = Criteria.where("f1").is("v1").or(Criteria.where("f2").is("v2"));
Criteria c2 = Criteria.where("f3").is("v3").or(Criteria.where("f4").is("v4"));
Criteria combined = c1.and(c2);

would require visiting the operator tree in depth-first order, opening and closing parentheses at the right places... or something like that. With only linear chaining it can get tricky to create criteria such as the one above.

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Oct 1, 2013

Anssi Törmä commented

There something else wrong in parsing nested criteria besides parenthesization. For the code in my previous comment, the query string is parsed as

f1:v1 OR f2:v2 OR f4:v4

So the AND operator is ignored and one field condition is missing!

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Oct 1, 2013

Anssi Törmä commented

I looked into the criteria parsing problem. I think the criteria chain approach is problematic. Chains may have criteria that have their own nested chains, and seems those are now ignored. Chains make it also difficult to see what the operators and operands are to apply the correct parenthesization.

I attached a fix proposal with some unit tests (spring-data-solr-criteria.zip). Instead of criteria chains, it tries to keep track of the operator tree structure. It's may not the prettiest or most extensively tested code ever, but I hope it helps

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 10, 2013

Christoph Strobl commented

Hi,
thank you and sorry for delayed answer. Will try to have a look as soon as possible

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 10, 2014

Christoph Strobl commented

there's a proposed solution available at github:issue/DATASOLR-105. It would be great to get some feedback

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