Having written tons of Java client code for querying elasticsearch, one thing I
appreciate with the various QueryBuilders is how closely they map to the actual
Lucene Query objects being the end result. Also, they are nicely composable,
and of course map almost 1:1 to ES JSON query dsl.

So if we want to evolve SolrJ's ability to construct complex queries, I'd 
propose
we couple the SolrJ builders to our JSON Query DSL and take the opportunity to
evolving, fixing and documenting that DSL in the process.

It would be a bonus if builders could output/serialize to legacy-query-string
as an option, but supporting only legacy would be a strange design choice.

Jan

> 20. aug. 2024 kl. 22:10 skrev Gus Heck <gus.h...@gmail.com>:
> 
> Also if expressed as xml the lucene classes can be sent to solr (not sure
> if we have a tool to express them as xml however)
> 
> https://solr.apache.org/guide/solr/latest/query-guide/other-parsers.html#xml-query-parser
> 
> On Tue, Aug 20, 2024 at 1:11 PM Mike Drob <md...@apache.org> wrote:
> 
>> At the risk of sounding ignorant, what is the advantage of this over using
>> Lucene classes to programmatically build queries and then toString those?
>> It's not a single class, but the lucene search package has always seemed
>> pretty straightforward to me.
>> 
>> https://lucene.apache.org/core/9_7_0/core/org/apache/lucene/search/package-summary.html#query
>> 
>> https://lucene.apache.org/core/9_7_0/core/org/apache/lucene/search/Query.html
>> 
>> If the goal is human readable query methods, I had previously done some of
>> the work in the opposite direction (matching queries to descriptions
>> instead of descriptions to queries) in test framework's QueryMatcher, might
>> be worth comparing against.
>> 
>> https://github.com/apache/solr/blob/main/solr/test-framework/src/java/org/apache/solr/util/QueryMatchers.java
>> 
>> 
>> 
>> On Tue, Aug 20, 2024 at 11:07 AM David Smiley <dsmi...@apache.org> wrote:
>> 
>>> Let's bikeshed before you write code, okay?  Otherwise you potentially
>>> waste time and/or grow attached to sunk costs.
>>> 
>>> Feedback:
>>> * avoid the word "term"; it already has Lucene definition and a Solr
>>> query parser but you're using it in a way that isn't either.  I
>>> recommend simply  for "fieldQuery" -- these queries target specific
>>> fields after all.
>>> * Can we avoid top level classes that the user must know about;
>>> instead having one class -- QueryBuilder (or named QueryStringBuilder)
>>> with factory methods that are easily discoverable?  Not a huge deal.
>>> * Instead of "Group", lets acknowledge these map to a BooleanQuery so
>>> I think "bool" in some way should be used instead.  Some bool builder
>>> can then have must() should() filter() methods without needing an
>>> enum.
>>> * Can't import any Lucene things
>>> 
>>> I'll add examples below of my feedback ideas.
>>> 
>>> On Tue, Aug 20, 2024 at 11:04 AM Geoffrey Slinker
>>> <geoffrey_slin...@yahoo.com.invalid> wrote:
>>> 
>>>> Instantiate a Term and set the values and call toString to get a string
>>> that can be used in a Standard Solr Query.
>>>>       Term term = new Term("pink panther").withBoost(1.5f);
>>>>       term. toString()
>>>> 
>>>>       Output: "pink panther"^1.5
>>>> 
>>>>       Term term = new Term("title", "pink panther").withBoost(1.5f);
>>>>       term. toString()
>>>> 
>>>>       Output: title:"pink panther"^1.5
>>> 
>>> final QueryStringBuilder B = new QueryStringBuilder(potential
>>> options); // immutable
>>> B.field("title", "ping panther").withBoost(1.5f).toString();
>>> 
>>> 
>>>>          TermGroup group = new TermGroup().with(Occur.
>>> MUST).withBoost(1.4f);
>>>>          group. addTerm(new Term("foo", "bar").withProximity(1));
>>>> 
>>>>          String query = group. toString();
>>>> 
>>>>          Output: +( foo:bar~1 )^1.4
>>> 
>>> the outer MUST is pointless but I'll recreate anyway:
>>> 
>>> final QueryStringBuilder B = new QueryStringBuilder(potential
>>> options); // immutable
>>> B.bool().must(B.fieldFuzzy("foo", "bar", 1).withBoost(1.4)).toString();
>>> 
>>>> Example:
>>>>          TermGroup group = new TermGroup().withConstantScore(5.0f);
>>>>          group. addTerm(new Term("foo", "bar").withProximity(1));
>>>> 
>>>>          String query = group. toString();
>>>> 
>>>>          Output: ( foo:bar~1 )^=5
>>> 
>>> final QueryStringBuilder B = new QueryStringBuilder(potential
>>> options); // immutable
>>> B.fieldFuzzy("foo", "bar", 1).withConstantScore(5.0f).toString();
>>> // no "group" terminology necessary
>>> 
>>>> Instead of using string manipulation to create complex query strings
>> the
>>> TermGroup allows complex queries to be built inside an object model that
>>> can be more easily changed.
>>>> If you need to generate a query like this:
>>>>  +(
>>>>        (
>>>>                title:"Grand Illusion"~1
>>>>                title:"Paradise Theatre"~1
>>>>        )^0.3
>>>>        (
>>>>                title:"Night At The Opera"~1
>>>>                title:"News Of The World"~1
>>>>        )^0.3
>>>>        (
>>>>                title:"Van Halen"~1
>>>>                title:1984~1
>>>>        )^0.3
>>>>  )
>>>> 
>>>> 
>>>>  The code to do so is as simple this:
>>>> 
>>>>      TermGroup group = new TermGroup().with(Occur. MUST);
>>>> 
>>>>      TermGroup favoriteStyx = group. addGroup().withBoost(0.3f);
>>>>      TermGroup favoriteQueen = group. addGroup().withBoost(0.3f);
>>>>      TermGroup favoriteVanHalen = group. addGroup().withBoost(0.3f);
>>>> 
>>>>      favoriteStyx. addTerm(new Term("title","Grand
>>> Illusion").with(Occur. SHOULD).withProximity(1));
>>>>      favoriteStyx. addTerm(new Term("title","Paradise
>>> Theatre").with(Occur. SHOULD).withProximity(1));
>>>> 
>>>>      favoriteQueen. addTerm(new Term("title","Night At The
>>> Opera").with(Occur. SHOULD).withProximity(1));
>>>>      favoriteQueen. addTerm(new Term("title","News Of The
>>> World").with(Occur. SHOULD).withProximity(1));
>>>> 
>>>>      favoriteVanHalen. addTerm(new Term("title","Van
>>> Halen").with(Occur. SHOULD).withProximity(1));
>>>>      favoriteVanHalen. addTerm(new Term("title","1984").with(Occur.
>>> SHOULD).withProximity(1));
>>>> 
>>> 
>>> // again, the outer bool MUST is pointless but will recreate your example
>>> 
>>> final QueryStringBuilder B = new QueryStringBuilder(potential
>>> options); // immutable
>>> 
>>> var favoriteStyx = B.bool();
>>> favoriteStyx.should(B.field("title", "Grand Illusion").withProximity(1));
>>> favoriteStyx.should(B.field("title", "Paradise
>> Theater").withProximity(1));
>>> 
>>> var favoriteQueen = B.bool();
>>> favoriteQueen.should(B.field("title", "Night At The
>>> Opera").withProximity(1));
>>> favoriteQueen.should(B.field("title", "News Of The
>>> World").withProximity(1));
>>> 
>>> var favoriteVanHalen = B.bool();
>>> favoriteVanHalen.should(B.field("title", "Van Halen").withProximity(1));
>>> favoriteVanHalen.should(B.field("title", "1984").withProximity(1));
>>> 
>>> B.bool().must( // pointless wrap
>>>  B.bool().should(favoriteStyx.withBoost(0.3f))
>>>               .should(favoriteQueen.withBoost(0.3f))
>>>               .should(favoriteVanHalen.withBoost(0.3f))
>>> ).toString();
>>> 
>>> ---
>>> If we imagine plausibly expanding support to write Solr JSON as an
>>> alternative, then it could affect the code choices.  Like
>>> toSolrLuceneSyntax() and toSolrQueryDsl().
>>> 
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscr...@solr.apache.org
>>> For additional commands, e-mail: dev-h...@solr.apache.org
>>> 
>>> 
>> 
> 
> 
> -- 
> http://www.needhamsoftware.com (work)
> https://a.co/d/b2sZLD9 (my fantasy fiction book)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@solr.apache.org
For additional commands, e-mail: dev-h...@solr.apache.org

Reply via email to